From e4b02023290624b899192f65626f0c0f60d5638c Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-206.sjc.redhat.com>
Date: Tue, 29 Mar 2016 10:39:27 -0700
Subject: [PATCH] Port symkey JNI to Java classes. Ticket #801 : Merge
 pki-symkey into jss

What is supported:

1. Everything that is needed to support Secure Channel Protocol 01.
2. Supports the nist sp800 kdf and the original kdf.
3. Supports key unwrapping used by TPS which was formerly in the symkey JNI.

Requires:

1. A new JSS that supports more advanced symkey operations such as key derivation, more advanced key
unwrapping , and a way to list and identify a given symmetric key by name. Version of new Jss will be forthcoming.

Still to do:

1. Port over the 2 or 3 SCP02 routines from Symkey to use this code.
2. The original symkey will remain in place until we can port over everything.
3. SCP03 support can be added later.

Audit fix.
---
 .../cms/src/com/netscape/cms/servlet/tks/KDF.java  |   67 +
 .../netscape/cms/servlet/tks/NistSP800_108KDF.java |  200 +++
 .../cms/servlet/tks/SecureChannelProtocol.java     | 1412 ++++++++++++++++++++
 .../com/netscape/cms/servlet/tks/StandardKDF.java  |  170 +++
 .../com/netscape/cms/servlet/tks/TokenServlet.java |  140 +-
 .../server/tps/processor/TPSProcessor.java         |   83 +-
 6 files changed, 1987 insertions(+), 85 deletions(-)
 create mode 100644 base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java
 create mode 100644 base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java
 create mode 100644 base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
 create mode 100644 base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java

diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java
new file mode 100644
index 0000000..54028af
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java
@@ -0,0 +1,67 @@
+package com.netscape.cms.servlet.tks;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
+public class KDF {
+    /* DES KEY Parity conversion table. Takes each byte >> 1 as an index, returns
+     * that byte with the proper parity bit set*/
+    static final int parityTable[] =
+    {
+            /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */
+            /* E */0x01, 0x02, 0x04, 0x07, 0x08, 0x0b, 0x0d, 0x0e,
+            /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */
+            /* O */0x10, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 0x1f,
+            /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */
+            /* O */0x20, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x2f,
+            /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */
+            /* E */0x31, 0x32, 0x34, 0x37, 0x38, 0x3b, 0x3d, 0x3e,
+            /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */
+            /* O */0x40, 0x43, 0x45, 0x46, 0x49, 0x4a, 0x4c, 0x4f,
+            /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */
+            /* E */0x51, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, 0x5e,
+            /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */
+            /* E */0x61, 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x6e,
+            /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */
+            /* O */0x70, 0x73, 0x75, 0x76, 0x79, 0x7a, 0x7c, 0x7f,
+            /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */
+            /* O */0x80, 0x83, 0x85, 0x86, 0x89, 0x8a, 0x8c, 0x8f,
+            /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */
+            /* E */0x91, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d, 0x9e,
+            /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */
+            /* E */0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xae,
+            /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */
+            /* O */0xb0, 0xb3, 0xb5, 0xb6, 0xb9, 0xba, 0xbc, 0xbf,
+            /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */
+            /* E */0xc1, 0xc2, 0xc4, 0xc7, 0xc8, 0xcb, 0xcd, 0xce,
+            /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */
+            /* O */0xd0, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc, 0xdf,
+            /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */
+            /* O */0xe0, 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xef,
+            /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */
+            /* E */0xf1, 0xf2, 0xf4, 0xf7, 0xf8, 0xfb, 0xfd, 0xfe, };
+
+    protected byte[] getDesParity(byte[] key) throws EBaseException {
+        String method = "KDF.getDesParity";
+        if (key == null
+                || (key.length != SecureChannelProtocol.DES2_LENGTH && key.length != SecureChannelProtocol.EIGHT_BYTES)) {
+            throw new EBaseException(method + " Incorrect input key !");
+        }
+
+        byte[] desKey = new byte[key.length];
+
+        for (int i = 0; i < key.length; i++) {
+            int index = key[i] & 0xff;
+            int finalIndex = index >> 1;
+
+            byte val = (byte) parityTable[finalIndex];
+            desKey[i] = val;
+
+        }
+
+        CMS.debug("desKey: " + desKey + " len: " + desKey.length);
+
+        return desKey;
+    }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java
new file mode 100644
index 0000000..cb614bd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java
@@ -0,0 +1,200 @@
+package com.netscape.cms.servlet.tks;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.HMACAlgorithm;
+import org.mozilla.jss.crypto.JSSMessageDigest;
+import org.mozilla.jss.crypto.SymmetricKey;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
+public class NistSP800_108KDF extends KDF {
+
+    static final int KDF_OUTPUT_SIZE_BITS = 384;
+    static final int KDF_OUTPUT_SIZE_BYTES = KDF_OUTPUT_SIZE_BITS / 8;
+    static final int KEY_DATA_SIZE_BYTES = KDF_OUTPUT_SIZE_BYTES / 3;
+
+    static final int KDD_SIZE_BYTES = 10; // expected KDD field length in bytes
+
+    static final byte KDF_LABEL = 0x04; // arbitra
+
+    static final int SHA256_LENGTH = 32;
+
+    SecureChannelProtocol protocol = null;
+
+    NistSP800_108KDF(SecureChannelProtocol protocol) {
+        this.protocol = protocol;
+    }
+
+    static public boolean useThisKDF(byte nistSP800_108KDFonKeyVersion, byte requestedKeyVersion) {
+        return (requestedKeyVersion >= nistSP800_108KDFonKeyVersion);
+    }
+
+    //*******************************************************************************
+    // Generates three PK11SymKey objects using the KDF_CM_SHA256HMAC_L384() function for key data.
+    // After calling KDF_CM_SHA256HMAC_L384, the function splits up the output, sets DES parity,
+    //   and imports the keys into the token.
+    //
+    // Careful:  This function currently generates the key data **IN RAM** using calls to NSS sha256.
+    //            The key data is then "unwrapped" (imported) to the NSS token and then erased from RAM.
+    //            (This means that a malicious actor on the box could steal the key data.)
+    //
+    // Note: Returned key material from the KDF is converted into keys according to the following:
+    //   * Bytes 0  - 15 : enc/auth key
+    //   * Bytes 16 - 31 : mac key
+    //   * Bytes 32 - 47 : kek key
+    //   We chose this order to conform with the key order used by the PUT KEY command.
+    //
+    //*******************************************************************************
+
+    public Map<String, SymmetricKey> computeCardKeys(SymmetricKey masterKey, byte[] context, CryptoToken token)
+            throws EBaseException {
+
+        String method = "NistSP800_108KDF.computeCardKeys:";
+
+        if (masterKey == null || context == null || token == null) {
+            throw new EBaseException(method + " Invlalid input parameters!");
+        }
+
+        Map<String, SymmetricKey> keys = new HashMap<String, SymmetricKey>();
+
+        byte[] kdf_output = null;
+
+        kdf_output = kdf_CM_SHA256_HMAC_L384(masterKey, context, KDF_LABEL, KDF_OUTPUT_SIZE_BYTES, token);
+
+        //Now create the 3 keys from only 48 of the 64 bytes...
+
+        byte[] enc = new byte[16];
+        byte[] mac = new byte[16];
+        byte[] kek = new byte[16];
+
+        System.arraycopy(kdf_output, 0 * SecureChannelProtocol.DES2_LENGTH, enc, 0, SecureChannelProtocol.DES2_LENGTH);
+        System.arraycopy(kdf_output, 1 * SecureChannelProtocol.DES2_LENGTH, mac, 0, SecureChannelProtocol.DES2_LENGTH);
+        System.arraycopy(kdf_output, 2 * SecureChannelProtocol.DES2_LENGTH, kek, 0, SecureChannelProtocol.DES2_LENGTH);
+
+        byte[] encFinal = this.getDesParity(enc);
+        byte[] macFinal = this.getDesParity(mac);
+        byte[] kekFinal = this.getDesParity(kek);
+
+        boolean showKeysOnlyForDebug = false;
+
+        if(showKeysOnlyForDebug) {
+            SecureChannelProtocol.debugByteArray(macFinal, " Nist macFinal: ");
+            SecureChannelProtocol.debugByteArray(encFinal, " Nist encFinal: ");
+            SecureChannelProtocol.debugByteArray(kekFinal, " Nist kekFinal: ");
+        }
+
+
+        Arrays.fill(enc, (byte) 0);
+        Arrays.fill(mac, (byte) 0);
+        Arrays.fill(kek, (byte) 0);
+
+        SymmetricKey macKey = protocol.unwrapSymKeyOnToken(token, macFinal, false);
+        SymmetricKey encKey = protocol.unwrapSymKeyOnToken(token, encFinal, false);
+        SymmetricKey kekKey = protocol.unwrapSymKeyOnToken(token, kekFinal, false);
+
+        Arrays.fill(encFinal, (byte) 0);
+        Arrays.fill(macFinal, (byte) 0);
+        Arrays.fill(kekFinal, (byte) 0);
+
+        keys.put(SecureChannelProtocol.macType, macKey);
+        keys.put(SecureChannelProtocol.encType, encKey);
+        keys.put(SecureChannelProtocol.kekType, kekKey);
+
+        return keys;
+
+    }
+
+    //*******************************************************************************
+    // Key Derivation Function in Counter Mode using PRF = SHA256HMAC (NIST SP 800-108)
+    //   Calculates 384 bits of diversified output from the provided master key (K_I)
+    //*******************************************************************************
+
+    private byte[] kdf_CM_SHA256_HMAC_L384(SymmetricKey masterKey, byte[] context, byte kdfLabel,
+            int kdfOutputSizeBytes, CryptoToken token) throws EBaseException {
+
+        String method = "NistSP800_108KDF.cm_SHA256_HMAC_L384:";
+
+        CMS.debug(method + " entering..");
+        final byte n = 2; // ceil(384 / (SHA256LENGTH * 8)) == 2
+        int L_BYTE_array_length = 2; // 384 = 0x0180 hex; 2 byte long representation
+
+        if (context == null) {
+            throw new EBaseException(method + " Input value context  must not be null.");
+        }
+        // sanity check that output buffer is large enough to contain 384 bits
+        if (kdfOutputSizeBytes < KDF_OUTPUT_SIZE_BYTES) {
+            throw new EBaseException(method + " Array \"output\" must be at least 48 bytes in size.");
+        }
+
+        // calculate size of temporary buffer
+        int HMAC_DATA_INPUT_SIZE = context.length + 3 + L_BYTE_array_length; // Don't change without reviewing code below.
+
+        // prevent integer overflow
+        if (HMAC_DATA_INPUT_SIZE < context.length) {
+            throw new EBaseException(method + " Input parameter context size is too large.");
+        }
+
+        byte L_BYTE_array[] = new byte[L_BYTE_array_length]; // Array to store L in BYTES
+        L_BYTE_array[0] = 0x01;
+        L_BYTE_array[1] = (byte) 0x80;
+
+        // Hash Input = context + 5 BYTES
+        byte[] hmac_data_input = new byte[HMAC_DATA_INPUT_SIZE];
+
+        byte[] K = new byte[n * SHA256_LENGTH];
+
+        hmac_data_input[1] = kdfLabel;
+        hmac_data_input[2] = 0x0;
+        System.arraycopy(context, 0, hmac_data_input, 3, context.length);
+        System.arraycopy(L_BYTE_array, 0, hmac_data_input, context.length + 3, 2);
+
+        byte[] outputHMAC256 = null;
+
+        for (byte i = 1; i <= n; i++) {
+            hmac_data_input[0] = i;
+            outputHMAC256 = sha256HMAC(masterKey, hmac_data_input, HMAC_DATA_INPUT_SIZE, token);
+            CMS.debug(method + "outputHMAC256 len: " + outputHMAC256.length);
+            System.arraycopy(outputHMAC256, 0, K, (i - 1) * SHA256_LENGTH, SHA256_LENGTH);
+        }
+
+        CMS.debug(method + " Returning: " + K.length + " bytes...");
+
+        return K;
+    }
+
+    private byte[] sha256HMAC(SymmetricKey masterKey, byte[] hmac_data_input, int hMAC_DATA_INPUT_SIZE,
+            CryptoToken token) throws EBaseException {
+
+        String method = "NistSP800_108KDF.sha256HMAC:";
+
+        CMS.debug(method + " Entering...");
+
+        byte[] digestBytes = null;
+
+        if (token == null) {
+            throw new EBaseException(method = " Invalid Crypto Token input!");
+        }
+
+        try {
+            JSSMessageDigest digest = token.getDigestContext(HMACAlgorithm.SHA256);
+            digest.initHMAC(masterKey);
+
+            digestBytes = digest.digest(hmac_data_input);
+        } catch (Exception e) {
+
+            CMS.debug(method + " Failure to HMAC the input data: " + e);
+            throw new EBaseException(method + e);
+        }
+
+        SecureChannelProtocol.debugByteArray(digestBytes, " output of sha256HMAC: ");
+
+        return digestBytes;
+    }
+
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
new file mode 100644
index 0000000..5cb7b06
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
@@ -0,0 +1,1412 @@
+package com.netscape.cms.servlet.tks;
+
+import java.io.ByteArrayOutputStream;
+import java.io.CharConversionException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Map;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.NoSuchTokenException;
+import org.mozilla.jss.crypto.BadPaddingException;
+import org.mozilla.jss.crypto.Cipher;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IllegalBlockSizeException;
+import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyGenerator;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapper;
+import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.SymmetricKey.NotExtractableException;
+import org.mozilla.jss.crypto.SymmetricKeyDeriver;
+import org.mozilla.jss.crypto.TokenException;
+
+import sun.security.pkcs11.wrapper.PKCS11Constants;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
+public class SecureChannelProtocol {
+
+    static String sharedSecretKeyName = null;
+    static String masterKeyPrefix = null;
+
+    static final int KEYLENGTH = 16;
+    static final int PREFIXLENGHT = 128;
+    static final int DES2_LENGTH = 16;
+    static final int DES3_LENGTH = 24;
+    static final int EIGHT_BYTES = 8;
+    static final int KEYNAMELENGTH = PREFIXLENGHT + 7;
+    static final String TRANSPORT_KEY_NAME = "sharedSecret";
+    static final String DEFKEYSET_NAME = "defKeySet";
+
+    static final String encType = "enc";
+    static final String macType = "mac";
+    static final String kekType = "kek";
+    static final String authType = "auth";
+    static final String dekType = "dek";
+    static final int PROTOCOL_ONE = 1;
+    static final int PROTOCOL_TWO = 2;
+    static final int PROTOCOL_THREE = 3;
+
+    private SymmetricKey transportKey = null;
+    CryptoManager cryptoManager = null;
+
+    public SecureChannelProtocol() {
+    }
+
+    public byte[] computeCryptogram_SCP01(
+            String selectedToken, String keyNickName, byte[] card_challenge,
+            byte[] host_challenge, byte[] keyInfo,
+            byte nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+            boolean nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+            byte[] xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+            byte[] xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+            int cryptogramType, byte[] authKeyArray, String useSoftToken_s, String keySet, String transportKeyName)
+            throws EBaseException {
+
+        String method = "SecureChannelProtocol.computeCryptogram_SCP01:";
+
+        CMS.debug(method + " Entering:  Type:  HOST=0 , CARD=1 : TYPE: " + cryptogramType);
+
+        if ((card_challenge == null || card_challenge.length != EIGHT_BYTES)
+                || (host_challenge == null || host_challenge.length != EIGHT_BYTES)) {
+
+            throw new EBaseException(method + " Invalid card challenge or host challenge!");
+
+        }
+
+        if( cryptogramType != 0 && cryptogramType != 1) {
+            throw new EBaseException(method + " Invalid cyrptgram type!");
+        }
+
+        byte[] cryptogram = null;
+
+        SymmetricKey authKey = this.computeSessionKey_SCP01(SecureChannelProtocol.encType, selectedToken, keyNickName,
+                card_challenge, host_challenge, keyInfo, nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd,
+                xCUID, xKDD, authKeyArray, useSoftToken_s, keySet, transportKeyName);
+
+        byte[] input = new byte[DES2_LENGTH];
+        byte[] icv = new byte[EIGHT_BYTES];
+
+        if (cryptogramType == 0) // compute host cryptogram
+        {
+            /* copy card and host challenge into input buffer */
+            for (int i = 0; i < EIGHT_BYTES; i++)
+            {
+                input[i] = card_challenge[i];
+            }
+            for (int i = 0; i < EIGHT_BYTES; i++)
+            {
+                input[EIGHT_BYTES + i] = host_challenge[i];
+            }
+        } // compute card cryptogram
+        else if (cryptogramType == 1)
+        {
+            for (int i = 0; i < EIGHT_BYTES; i++)
+            {
+                input[i] = host_challenge[i];
+            }
+            for (int i = 0; i < EIGHT_BYTES; i++)
+            {
+                input[EIGHT_BYTES + i] = card_challenge[i];
+            }
+
+        }
+        cryptogram = computeMAC_SCP01(authKey, input, icv, selectedToken);
+
+        SecureChannelProtocol.debugByteArray(cryptogram, " Output of computeCrytptogram type: " + cryptogramType);
+
+        return cryptogram;
+    }
+
+    public SymmetricKey computeSessionKey_SCP02(
+            String selectedToken, String keyNickName,
+            byte[] keyInfo,
+            byte nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+            boolean nistSP800_108KdfUseCuidAsKdd, byte[] xCUID, byte[] xKDD, byte[] macKeyArray,
+            byte[] sequenceCounter, byte[] derivationConstant,
+            String useSoftToken_s, String keySet,
+            String transportKeyName) throws EBaseException {
+
+        String method = "SecureChannelProtocol.computeSessionKey_SCP01:";
+
+        CMS.debug(method + " entering... ");
+
+        throw new EBaseException(method + " Not yet implemented!");
+    }
+
+    public SymmetricKey computeSessionKey_SCP01(String keyType,
+            String selectedToken, String keyNickName, byte[] card_challenge,
+            byte[] host_challenge, byte[] keyInfo,
+            byte nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+            boolean nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+            byte[] xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+            byte[] xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+            byte[] devKeyArray, String useSoftToken_s, String keySet, String transportKeyName) throws EBaseException {
+
+        String method = "SecureChannelProtocol.computeSessionKey_SCP01:";
+
+        CMS.debug(method + " entering... requested type: " + keyType);
+
+        // This gets set if there is no input card challenge and host challenge
+        // Allows this routine to be used for the "encryptData" routine built on top.
+
+        boolean noDerive = false;
+
+        if (keyType == null || devKeyArray == null || keyInfo == null
+                || keySet == null || transportKeyName == null || (keyInfo == null || keyInfo.length < 2)) {
+            throw new EBaseException(method + "Invalid input!");
+        }
+
+        if (xCUID == null || xCUID.length <= 0) {
+            throw new EBaseException(method + "CUID invalid size!");
+        }
+
+        if (xKDD == null || xKDD.length != NistSP800_108KDF.KDD_SIZE_BYTES) {
+            throw new EBaseException(method + "KDD invalid size!");
+        }
+
+        if (card_challenge == null && host_challenge == null) {
+            noDerive = true;
+            CMS.debug(method + " NoDerive mode: true");
+        } else {
+            if (card_challenge == null || host_challenge == null) {
+                throw new EBaseException(method + " Invalid input!");
+            }
+
+            CMS.debug(method + " NoDerive mode: false");
+        }
+
+        CMS.debug(method + " entering. nickname: " + keyNickName + " selectedToken: " + selectedToken);
+        CMS.debug(method + " nistSP800_108kdfOnKeyVersion: " + nistSP800_108KdfOnKeyVersion);
+
+        CryptoManager cm = null;
+        CryptoToken token = null;
+        try {
+            cm = CryptoManager.getInstance();
+            token = returnTokenByName(selectedToken, cm);
+        } catch (NotInitializedException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+
+        } catch (NoSuchTokenException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        sharedSecretKeyName = SecureChannelProtocol.getSharedSecretKeyName(transportKeyName);
+        transportKey = getSharedSecretKey(token);
+
+        String keyNameStr = null;
+
+        SymmetricKey sessionKey = null;
+        SymmetricKey masterKey = null;
+
+        if (keyNickName == null) {
+            keyNameStr = this.getKeyName(keyInfo);
+        } else {
+            keyNameStr = keyNickName;
+        }
+
+        byte[] context = null;
+
+        if (nistSP800_108KdfUseCuidAsKdd == true) {
+            context = xCUID;
+        } else {
+            context = xKDD;
+        }
+
+        if ((keyInfo[0] == 0x1 && keyInfo[1] == 0x1 && keyNameStr.equals("#01#01")) ||
+                (keyInfo[0] == -1 && keyNameStr.indexOf("#FF") != -1))
+
+        {
+            /* default manufacturers key */
+
+            String finalKeyType = keyType;
+
+            SymmetricKey devSymKey = returnDeveloperSymKey(token, finalKeyType, keySet, devKeyArray);
+
+            // Create the auth with is the same as enc, might need it later.
+            if (keyType.equals(encType)) {
+                returnDeveloperSymKey(token, authType, keySet, devKeyArray);
+            }
+
+            if (noDerive == true) {
+                sessionKey = devSymKey;
+            } else {
+                sessionKey = deriveKey_SCP01(token, devSymKey, host_challenge, card_challenge);
+            }
+
+        } else {
+
+            SymmetricKey devKey = null;
+            CMS.debug(method + "In master key mode.");
+
+            masterKey = getSymKeyByName(token, keyNameStr);
+
+            if (NistSP800_108KDF.useThisKDF(nistSP800_108KdfOnKeyVersion, keyInfo[1])) {
+                CMS.debug(method + " ComputeSessionKey NistSP800_108KDF code: Using NIST SP800-108 KDF.");
+
+                NistSP800_108KDF nistKDF = new NistSP800_108KDF(this);
+
+                Map<String, SymmetricKey> keys = null;
+                try {
+                    keys = nistKDF.computeCardKeys(masterKey, context, token);
+                } catch (EBaseException e) {
+                    CMS.debug(method + "Can't compute card keys! " + e);
+                    throw e;
+                }
+
+                devKey = keys.get(keyType);
+
+            } else {
+                StandardKDF standardKDF = new StandardKDF(this);
+                CMS.debug(method + " ComputeSessionKey NistSP800_108KDF code: Using original KDF.");
+                byte[] data = standardKDF.getDiversificationData(context, keyType);
+                devKey = standardKDF.computeCardKey(masterKey, data, token, PROTOCOL_ONE);
+            }
+
+            if (noDerive == true) {
+                sessionKey = devKey;
+            } else {
+                sessionKey = deriveKey_SCP01(token, devKey, host_challenge, card_challenge);
+            }
+        }
+
+        return sessionKey;
+    }
+
+    private SymmetricKey deriveKey_SCP01(CryptoToken token, SymmetricKey cardKey, byte[] host_challenge,
+            byte[] card_challenge)
+            throws EBaseException {
+        String method = "SecureChannelProtocol.deriveKey_SCP01:";
+        CMS.debug(method + "entering..");
+
+        if (cardKey == null || token == null) {
+            throw new EBaseException(method + " Invalid input data!");
+        }
+
+        byte[] derivationData = new byte[KEYLENGTH];
+
+        SymmetricKey derivedKey = null;
+
+        for (int i = 0; i < 4; i++)
+        {
+            derivationData[i] = card_challenge[i + 4];
+            derivationData[i + 4] = host_challenge[i];
+            derivationData[i + 8] = card_challenge[i];
+            derivationData[i + 12] = host_challenge[i + 4];
+        }
+
+        SymmetricKeyDeriver encryptDes3;
+        try {
+            encryptDes3 = token.getSymmetricKeyDeriver();
+
+            encryptDes3.initDerive(
+                    cardKey, /* PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA */4354L, derivationData, null,
+                    PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 16);
+
+            derivedKey = encryptDes3.derive();
+
+        } catch (TokenException | InvalidKeyException e) {
+            CMS.debug(method + "Unable to derive the key with the proper mechanism!");
+            throw new EBaseException(e);
+        }
+
+        return derivedKey;
+    }
+
+    public SymmetricKey getSharedSecretKey(CryptoToken token) throws EBaseException {
+
+        String method = "SecureChannelProtocol.getSharedSecretKey:";
+
+        if (transportKey == null) {
+            transportKey = getSymKeyByName(token, sharedSecretKeyName);
+        }
+
+        if (transportKey == null) {
+            throw new EBaseException(method + "Can't locate shared secret key in token db.");
+        }
+
+        return transportKey;
+    }
+
+    private String getKeyName(byte[] keyVersion) {
+        String keyName = null;
+
+        if (keyVersion == null || keyVersion.length != 2) {
+            return null;
+        }
+
+        keyName = "#" + keyVersion[0] + "#" + keyVersion[1];
+
+        return keyName;
+    }
+
+    public static String getSharedSecretKeyName(String name) throws EBaseException {
+
+        String method = "SecureChannelProtocol.getSharedSecretKeyName:";
+        CMS.debug(method + " Entering...");
+
+        if (name != null && SecureChannelProtocol.sharedSecretKeyName == null) {
+            SecureChannelProtocol.sharedSecretKeyName = name;
+        }
+
+        if (SecureChannelProtocol.sharedSecretKeyName == null) {
+            throw new EBaseException(method + " Can not find shared secret key name!");
+        }
+
+        return SecureChannelProtocol.sharedSecretKeyName;
+    }
+
+    public static String setSharedSecretKeyName(String name) throws EBaseException {
+        return SecureChannelProtocol.getSharedSecretKeyName(name);
+    }
+
+    private SymmetricKey returnDeveloperSymKey(CryptoToken token, String keyType, String keySet, byte[] inputKeyArray)
+            throws EBaseException {
+
+        SymmetricKey devKey = null;
+
+        String method = "SecureChannelProtocol.returnDeveloperSymKey:";
+
+        String devKeyName = keySet + "-" + keyType + "Key";
+        CMS.debug(method + " entering.. searching for key: " + devKeyName);
+
+        if (token == null || keyType == null || keySet == null) {
+            throw new EBaseException(method + "Invalid input data!");
+        }
+
+        devKey = getSymKeyByName(token, devKeyName);
+
+        if (devKey == null) {
+            //Put the key there and leave it
+
+            byte[] des3InputKey = null;
+
+            if (inputKeyArray == null) {
+                throw new EBaseException(method + "Input key is null and has to be non null when importing...");
+            }
+            int inputLen = inputKeyArray.length;
+
+            CMS.debug(method + " inputKeyArray.length: " + inputLen);
+
+            if (inputLen != DES3_LENGTH && inputLen != DES2_LENGTH) {
+                throw new EBaseException(method + "invalid input key length!");
+            }
+
+            if (inputLen == DES2_LENGTH) {
+                des3InputKey = new byte[DES3_LENGTH];
+                System.arraycopy(inputKeyArray, 0, des3InputKey, 0, DES2_LENGTH);
+                System.arraycopy(inputKeyArray, 0, des3InputKey, DES2_LENGTH, EIGHT_BYTES);
+
+            } else {
+                System.arraycopy(inputKeyArray, 0, des3InputKey, 0, DES3_LENGTH);
+            }
+
+            SecureChannelProtocol.debugByteArray(des3InputKey, "Developer key to import: " + keyType + ": ");
+
+            devKey = unwrapSymKeyOnToken(token, des3InputKey, true);
+            devKey.setNickName(devKeyName);
+        } else {
+            CMS.debug(method + " Found sym key: " + devKeyName);
+        }
+        return devKey;
+    }
+
+    public SymmetricKey unwrapSymKeyOnToken(CryptoToken token, SymmetricKey unwrappingKey, byte[] inputKeyArray,
+            boolean isPerm)
+            throws EBaseException {
+
+        String method = "SecureChannelProtocol.unwrapSymKeyOnToken:";
+        CMS.debug(method + "Entering...");
+        SymmetricKey unwrapped = null;
+
+        if (token == null || unwrappingKey == null) {
+            throw new EBaseException(method + "Invalid input!");
+        }
+
+        if (inputKeyArray == null || (inputKeyArray.length != DES3_LENGTH && inputKeyArray.length != DES2_LENGTH)) {
+            throw new EBaseException(method + "No raw array to use to create key!");
+        }
+
+        byte[] finalKeyArray = null;
+
+        if (inputKeyArray.length == DES2_LENGTH) {
+            finalKeyArray = SecureChannelProtocol.makeDes3FromDes2(inputKeyArray);
+        }
+
+        Cipher encryptor = null;
+        byte[] wrappedKey = null;
+
+        try {
+            encryptor = token.getCipherContext(EncryptionAlgorithm.DES3_ECB);
+
+            encryptor.initEncrypt(unwrappingKey);
+
+            if (finalKeyArray != null) {
+                wrappedKey = encryptor.doFinal(finalKeyArray);
+            } else {
+                wrappedKey = encryptor.doFinal(inputKeyArray);
+            }
+
+            CMS.debug(method + " done enrypting data");
+
+            KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
+            keyWrap.initUnwrap(unwrappingKey, null);
+
+            if (isPerm == true) {
+                unwrapped = keyWrap.unwrapSymmetricPerm(wrappedKey,
+                        SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP, 0);
+            } else {
+                unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP, 0);
+            }
+
+        } catch (Exception e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        } finally {
+            if (finalKeyArray != null) {
+                Arrays.fill(finalKeyArray, (byte) 0);
+            }
+        }
+
+        CMS.debug(method + "Returning symkey: " + unwrapped);
+
+        return unwrapped;
+    }
+
+    public SymmetricKey unwrapWrappedSymKeyOnToken(CryptoToken token, SymmetricKey unwrappingKey, byte[] inputKeyArray,
+            boolean isPerm)
+            throws EBaseException {
+
+        String method = "SecureChannelProtocol.unwrapWrappedSymKeyOnToken:";
+        CMS.debug(method + "Entering...");
+        SymmetricKey unwrapped = null;
+        SymmetricKey finalUnwrapped = null;
+
+        if (token == null || unwrappingKey == null) {
+            throw new EBaseException(method + "Invalid input!");
+        }
+
+        if (inputKeyArray == null || (inputKeyArray.length != DES3_LENGTH && inputKeyArray.length != DES2_LENGTH)) {
+            throw new EBaseException(method + "No raw array to use to create key!");
+        }
+
+        try {
+            KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
+            keyWrap.initUnwrap(unwrappingKey, null);
+
+            if (isPerm) {
+                unwrapped = keyWrap.unwrapSymmetricPerm(inputKeyArray,
+                        SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP, inputKeyArray.length);
+            } else {
+                unwrapped = keyWrap.unwrapSymmetric(inputKeyArray, SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP,
+                        inputKeyArray.length);
+            }
+
+            finalUnwrapped = makeDes3KeyDerivedFromDes2(unwrapped, token.getName());
+
+        } catch (Exception e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        CMS.debug(method + "Returning symkey: " + unwrapped);
+
+        return finalUnwrapped;
+    }
+
+    public SymmetricKey unwrapSymKeyOnToken(CryptoToken token, byte[] inputKeyArray, boolean isPerm)
+            throws EBaseException {
+
+        String method = "SecureChannelProtocol.unwrapSymKeyOnToken:";
+        CMS.debug(method + "Entering...");
+        SymmetricKey unwrapped = null;
+
+        if (token == null) {
+            throw new EBaseException(method + "Invalide crypto token!");
+        }
+
+        if (inputKeyArray == null || (inputKeyArray.length != DES3_LENGTH && inputKeyArray.length != DES2_LENGTH)) {
+            throw new EBaseException(method + "No raw array to use to create key!");
+        }
+
+        SymmetricKey transport = getSharedSecretKey(token);
+        unwrapped = this.unwrapSymKeyOnToken(token, transport, inputKeyArray, isPerm);
+
+        CMS.debug(method + "Returning symkey: " + unwrapped);
+
+        return unwrapped;
+    }
+
+    public SymmetricKey unwrapWrappedSymKeyOnToken(CryptoToken token, byte[] wrappedKeyArray, boolean isPerm)
+            throws EBaseException {
+
+        String method = "SecureChannelProtocol.unwrapWrappedSymKeyOnToken:";
+        CMS.debug(method + "Entering...");
+        SymmetricKey unwrapped = null;
+
+        if (token == null) {
+            throw new EBaseException(method + "Invalide crypto token!");
+        }
+
+        if (wrappedKeyArray == null || (wrappedKeyArray.length != DES3_LENGTH && wrappedKeyArray.length != DES2_LENGTH)) {
+            throw new EBaseException(method + "No raw array to use to create key!");
+        }
+
+        SymmetricKey transport = getSharedSecretKey(token);
+        unwrapped = this.unwrapSymKeyOnToken(token, transport, wrappedKeyArray, isPerm);
+
+        CMS.debug(method + "Returning symkey: " + unwrapped);
+
+        return unwrapped;
+    }
+
+    public static SymmetricKey getSymKeyByName(CryptoToken token, String name) throws EBaseException {
+
+        String method = "SecureChannelProtocol.getSymKeyByName:";
+        if (token == null || name == null) {
+            throw new EBaseException(method + "Invalid input data!");
+        }
+        SymmetricKey[] keys;
+
+        CMS.debug(method + "Searching for sym key: " + name);
+        try {
+            keys = token.getCryptoStore().getSymmetricKeys();
+        } catch (TokenException e) {
+            throw new EBaseException(method + "Can't get the list of symmetric keys!");
+        }
+        int len = keys.length;
+        for (int i = 0; i < len; i++) {
+            SymmetricKey cur = keys[i];
+            if (cur != null) {
+                if (name.equals(cur.getNickName())) {
+                    CMS.debug(method + "Found key: " + name);
+                    return cur;
+                }
+            }
+        }
+
+        CMS.debug(method + " Sym Key not found.");
+        return null;
+    }
+
+    public CryptoToken returnTokenByName(String name, CryptoManager manager) throws NoSuchTokenException {
+
+        if (name == null || manager == null)
+            throw new NoSuchTokenException();
+
+        if (name.equals("internal") || name.equals("Internal KeyStorage Token")) {
+            return manager.getInternalKeyStorageToken();
+        } else {
+            return manager.getTokenByName(name);
+        }
+
+    }
+
+    public static byte[] makeDes3FromDes2(byte[] des2) {
+
+        if (des2 == null || des2.length != SecureChannelProtocol.DES2_LENGTH) {
+            return null;
+        }
+
+        byte[] des3 = new byte[SecureChannelProtocol.DES3_LENGTH];
+
+        System.arraycopy(des2, 0, des3, 0, SecureChannelProtocol.DES2_LENGTH);
+        System.arraycopy(des2, 0, des3, DES2_LENGTH, EIGHT_BYTES);
+
+        return des3;
+    }
+
+    public static void debugByteArray(byte[] array, String message) {
+
+        CMS.debug("About to dump array: " + message);
+
+        if (array == null) {
+            CMS.debug("Array to dump is empty!");
+            return;
+        }
+
+        CMS.debug("################### ");
+
+        String result = getHexString(array);
+        CMS.debug(result);
+    }
+
+    final protected static char[] hex = "0123456789abcdef".toCharArray();
+
+    public static String getHexString(byte[] bytes) {
+
+        char[] hexChars = new char[bytes.length * 3];
+        for (int j = 0; j < bytes.length; j++) {
+            int v = bytes[j] & 0xFF;
+            hexChars[j * 3] = hex[v >>> 4];
+            hexChars[j * 3 + 1] = hex[v & 0x0F];
+            hexChars[j * 3 + 2] = ':';
+        }
+        return new String(hexChars);
+    }
+
+    public CryptoManager getCryptoManger() throws EBaseException {
+        String method = "SecureChannelProtocol.getCryptoManager";
+        CryptoManager cm = null;
+
+        if (cryptoManager != null)
+            return cryptoManager;
+
+        try {
+            cm = CryptoManager.getInstance();
+        } catch (NotInitializedException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+
+        }
+
+        cryptoManager = cm;
+
+        return cryptoManager;
+
+    }
+
+    public static byte[] longToBytes(long x) {
+        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
+        buffer.putLong(x);
+        return buffer.array();
+    }
+
+    // Generate 24 key, but with a DES2 key converted to DES3
+    // This needed to appease the server side keygen and the coollkey applet.
+    public SymmetricKey generateSymKey(String selectedToken) throws EBaseException {
+        String method = "SecureChannelProtocol.generateSymKey:";
+
+        CMS.debug(method + " entering , token: " + selectedToken);
+        SymmetricKey symKey = null;
+        SymmetricKey symKeyFinal = null;
+
+        if (selectedToken == null) {
+            throw new EBaseException(method + " Invalid input data!");
+        }
+
+        try {
+            CryptoManager cm = this.getCryptoManger();
+            CryptoToken token = returnTokenByName(selectedToken, cm);
+
+            KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
+
+            symKey = kg.generate();
+
+            symKeyFinal = this.makeDes3KeyDerivedFromDes2(symKey, selectedToken);
+
+        } catch (NoSuchAlgorithmException | TokenException | NoSuchTokenException | IllegalStateException
+                | CharConversionException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        return symKeyFinal;
+
+    }
+
+    public byte[] ecbEncrypt(SymmetricKey devKey, SymmetricKey symKey, String selectedToken) throws EBaseException {
+        byte[] result = null;
+        String method = "SecureChannelProtocol.ecbEncrypt:";
+        CMS.debug(method + " Entering...");
+
+        if (devKey == null || symKey == null || selectedToken == null) {
+            throw new EBaseException(method + " Invalid input parameters.");
+        }
+
+        SymmetricKey des2 = this.extractDes2FromDes3(symKey, selectedToken);
+
+        result = this.wrapSessionKey(selectedToken, des2, devKey);
+
+        SecureChannelProtocol.debugByteArray(result, " Wrapped des2 key");
+
+        return result;
+    }
+
+    public SymmetricKey makeDes3KeyDerivedFromDes2(SymmetricKey des3Key, String selectedToken) throws EBaseException {
+        SymmetricKey des3 = null;
+
+        String method = "SecureChannelProtocol.makeDes3KeyDerivedFromDes2:";
+
+        CMS.debug(method + " Entering ...");
+
+        if (des3Key == null || selectedToken == null) {
+            throw new EBaseException(method + " Invalid input data!");
+        }
+
+        try {
+            CryptoManager cm = this.getCryptoManger();
+            CryptoToken token = returnTokenByName(selectedToken, cm);
+
+            long bitPosition = 0;
+
+            byte[] param = SecureChannelProtocol.longToBytes(bitPosition);
+
+            SymmetricKey extracted16 = this.extractDes2FromDes3(des3Key, selectedToken);
+
+            SymmetricKeyDeriver extract8 = token.getSymmetricKeyDeriver();
+
+            extract8.initDerive(
+                    extracted16, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY, param, null,
+                    PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE, 8);
+
+            SymmetricKey extracted8 = extract8.derive();
+
+            CMS.debug(method + " extracted8 key: " + extracted8);
+
+            SymmetricKeyDeriver concat = token.getSymmetricKeyDeriver();
+            concat.initDerive(
+                    extracted16, extracted8, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY, null, null,
+                    PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 0);
+
+            des3 = concat.derive();
+
+        } catch (NoSuchTokenException | IllegalStateException | TokenException | InvalidKeyException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        return des3;
+    }
+
+    public SymmetricKey extractDes2FromDes3(SymmetricKey baseKey, String selectedToken) throws EBaseException {
+        String method = "SecureChannelProtocol.extractDes2FromDes3:";
+        CMS.debug(method + " Entering: ");
+
+        SymmetricKey extracted16 = null;
+
+        if (baseKey == null || selectedToken == null) {
+            throw new EBaseException(method + " Invalid input data.");
+        }
+
+        try {
+            CryptoManager cm = this.getCryptoManger();
+            CryptoToken token = returnTokenByName(selectedToken, cm);
+
+            long bitPosition = 0;
+
+            byte[] param = SecureChannelProtocol.longToBytes(bitPosition);
+
+            SymmetricKeyDeriver extract16 = token.getSymmetricKeyDeriver();
+            extract16.initDerive(
+                    baseKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY, param, null,
+                    PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE, 16);
+
+            extracted16 = extract16.derive();
+
+        } catch (NoSuchTokenException | IllegalStateException | TokenException | InvalidKeyException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        return extracted16;
+    }
+
+    public byte[] wrapSessionKey(String tokenName, SymmetricKey sessionKey, SymmetricKey wrappingKey)
+            throws EBaseException {
+        //Now wrap the key for the trip back to TPS with shared secret transport key
+
+        String method = "SecureChannelProtocol.wrapSessionKey";
+
+        KeyWrapper keyWrap = null;
+        byte[] wrappedSessKeyData = null;
+
+        if (tokenName == null || sessionKey == null) {
+            throw new EBaseException(method + " Invalid input data.");
+        }
+
+        SymmetricKey wrapper = null;
+
+        if (wrappingKey == null) {
+            wrapper = transportKey;
+        } else {
+            wrapper = wrappingKey;
+        }
+
+        try {
+            CryptoManager cm = this.getCryptoManger();
+            CryptoToken token = returnTokenByName(tokenName, cm);
+
+            keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
+            keyWrap.initWrap(wrapper, null);
+            wrappedSessKeyData = keyWrap.wrap(sessionKey);
+        } catch (NoSuchAlgorithmException | TokenException | InvalidKeyException | InvalidAlgorithmParameterException
+                | NoSuchTokenException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        CMS.debug(method + " About to return session key: " + wrappedSessKeyData);
+
+        return wrappedSessKeyData;
+
+    }
+
+    public byte[] computeDes3EcbEncryption(SymmetricKey desKey, String selectedToken, byte[] input)
+            throws EBaseException {
+
+        String method = "SecureChannelProtocol.computeDes3EcbEncryption";
+        byte[] output = null;
+
+        if (desKey == null || selectedToken == null) {
+            throw new EBaseException(method + " Invalid input data.");
+        }
+
+        try {
+            CryptoManager cm = this.getCryptoManger();
+            CryptoToken token = returnTokenByName(selectedToken, cm);
+            Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.DES3_ECB);
+            encryptor.initEncrypt(desKey);
+            output = encryptor.doFinal(input);
+
+        } catch (EBaseException | NoSuchTokenException | NoSuchAlgorithmException | TokenException
+                | InvalidKeyException | InvalidAlgorithmParameterException |
+                IllegalStateException | IllegalBlockSizeException | BadPaddingException e) {
+
+            CMS.debug(method + e);
+            throw new EBaseException(method + e);
+        }
+        return output;
+    }
+
+    public byte[] computeKeyCheck(SymmetricKey desKey, String selectedToken) throws EBaseException {
+
+        String method = "SecureChannelProtocol.computeKeyCheck:";
+
+        CMS.debug(method + " Entering...");
+
+        byte[] input = new byte[EIGHT_BYTES];
+        byte[] finalOutput = new byte[3];
+
+        if (desKey == null || selectedToken == null) {
+            throw new EBaseException(method + " Invalid input data.");
+        }
+
+        byte[] output = null;
+
+        try {
+            output = computeDes3EcbEncryption(desKey, selectedToken, input);
+        } catch (EBaseException e) {
+            CMS.debug(method + e);
+            throw e;
+
+        }
+
+        //Get the 3 bytes needed
+        System.arraycopy(output, 0, finalOutput, 0, 3);
+
+        SecureChannelProtocol.debugByteArray(finalOutput, "Calculated KeyCheck Value:");
+
+        return finalOutput;
+    }
+
+    public byte[] computeMAC_SCP01(SymmetricKey symKey, byte[] input, byte[] icv, String selectedToken)
+            throws EBaseException {
+        byte[] output = null;
+        byte[] result = null;
+
+        String method = "SecureChannelProtocol.computeMAC_SCP01:";
+
+        CMS.debug(method + " Entering...");
+
+        if (symKey == null || input == null || icv == null || icv.length != EIGHT_BYTES) {
+            throw new EBaseException(method + " invalid input data!");
+        }
+        int inputLen = input.length;
+
+        byte[] macPad = new byte[8];
+        macPad[0] = (byte) 0x80;
+
+        CryptoToken token = null;
+
+        try {
+
+            CryptoManager cm = this.getCryptoManger();
+            token = returnTokenByName(selectedToken, cm);
+
+            Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES3_ECB);
+
+            result = new byte[EIGHT_BYTES];
+            System.arraycopy(icv, 0, result, 0, EIGHT_BYTES);
+
+            /* 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[i] ^ input[inputOffset + i]);
+                    result[i] = a;
+                }
+                cipher.initEncrypt(symKey);
+                byte[] ciphResult = cipher.doFinal(result);
+
+                if (ciphResult.length != result.length) {
+                    throw new EBaseException(method + " Invalid cipher!");
+                }
+
+                System.arraycopy(ciphResult, 0, result, 0, EIGHT_BYTES);
+
+                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[i] ^ input[inputOffset + i]);
+                result[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[i] ^ macPad[padOffset++]);
+                result[i] = a;
+                i++;
+            }
+
+            cipher.initEncrypt(symKey);
+            output = cipher.doFinal(result);
+
+            if (output.length != result.length) {
+                throw new EBaseException(method + " Invalid cipher!");
+            }
+
+        } catch (Exception e) {
+            throw new EBaseException(method + " Cryptographic problem encountered! " + e.toString());
+        }
+
+        SecureChannelProtocol.debugByteArray(output, method + " output: ");
+
+        return output;
+    }
+
+    public byte[] diversifyKey(String tokenName,
+            String newTokenName,
+            String oldMasterKeyName,
+            String newMasterKeyName,
+            byte[] oldKeyInfo,
+            byte[] newKeyInfo,
+            byte nistSP800_108KdfOnKeyVersion,
+            boolean nistSP800_108KdfUseCuidAsKdd,
+            byte[] CUIDValue,
+            byte[] KDD,
+            byte[] kekKeyArray,
+            String useSoftToken, String keySet, byte protocol) throws EBaseException {
+
+        String method = "SecureChannelProtocol.diversifyKey:";
+
+        CMS.debug(method + " Entering ... newTokenName: " + newTokenName);
+
+        SymmetricKey masterKey = null;
+        SymmetricKey oldMasterKey = null;
+
+        byte[] KDCenc = null;
+        byte[] KDCmac = null;
+        byte[] KDCkek = null;
+
+        SymmetricKey old_mac_sym_key = null;
+        SymmetricKey old_enc_sym_key = null;
+        SymmetricKey old_kek_sym_key = null;
+
+        SymmetricKey encKey = null;
+        SymmetricKey macKey = null;
+        SymmetricKey kekKey = null;
+
+        // The final answer
+        byte[] output = null;
+
+        if (oldMasterKeyName == null || oldKeyInfo == null || newKeyInfo == null
+                || keySet == null) {
+            throw new EBaseException(method + "Invalid input!");
+        }
+
+        if (oldKeyInfo.length < 2 || newKeyInfo.length < 2) {
+            throw new EBaseException(method + " Invalid input length for keyinfo versions.");
+        }
+
+        String fullNewMasterKeyName = getFullMasterKeyName(newMasterKeyName);
+        String fullOldMasterKeyName = getFullMasterKeyName(oldMasterKeyName);
+
+        CryptoManager cm = null;
+        CryptoToken token = null;
+        CryptoToken newToken = null;
+        try {
+            cm = CryptoManager.getInstance();
+            token = returnTokenByName(tokenName, cm);
+            if (newTokenName != null) {
+                newToken = returnTokenByName(newTokenName, cm);
+            }
+        } catch (NotInitializedException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+
+        } catch (NoSuchTokenException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        try {
+            if (newToken != null) {
+                masterKey = getSymKeyByName(newToken, fullNewMasterKeyName);
+            }
+            oldMasterKey = getSymKeyByName(token, fullOldMasterKeyName);
+        } catch (EBaseException e) {
+            masterKey = null;
+            CMS.debug(method + " Master key is null, possibly ok in moving from keyset 2 to 1");
+
+            if (oldMasterKey == null) {
+                throw new EBaseException(method + " Can't retrieve old master key!");
+            }
+        }
+
+        SecureChannelProtocol.debugByteArray(oldKeyInfo, " oldKeyInfo: ");
+        SecureChannelProtocol.debugByteArray(newKeyInfo, " newKeyInfo: ");
+
+        byte oldKeyVersion = oldKeyInfo[0];
+        byte newKeyVersion = newKeyInfo[0];
+
+        byte[] context = null;
+
+        if (nistSP800_108KdfUseCuidAsKdd == true) {
+            context = CUIDValue;
+        } else {
+            context = KDD;
+        }
+
+        // We may need either or both of these
+
+        StandardKDF standardKDF = new StandardKDF(this);
+        NistSP800_108KDF nistKDF = new NistSP800_108KDF(this);
+
+        KDCenc = standardKDF.getDiversificationData(KDD, SecureChannelProtocol.encType);
+        KDCmac = standardKDF.getDiversificationData(KDD, SecureChannelProtocol.macType);
+        KDCkek = standardKDF.getDiversificationData(KDD, SecureChannelProtocol.kekType);
+
+        if (protocol == PROTOCOL_ONE) {
+            if (checkForDeveloperKeySet(oldMasterKeyName) == true) {
+                CMS.debug(method + " Developer key set case: ");
+            } else {
+                CMS.debug(method + " Not Developer key set case: ");
+
+                if (NistSP800_108KDF.useThisKDF(nistSP800_108KdfOnKeyVersion, oldKeyVersion)) {
+                    CMS.debug(method + " NistSP800_108KDF code: Using NIST SP800-108 KDF.");
+
+                    Map<String, SymmetricKey> keys = null;
+                    try {
+                        keys = nistKDF.computeCardKeys(oldMasterKey, context, token);
+                    } catch (EBaseException e) {
+                        CMS.debug(method + "Can't compute card keys! " + e);
+                        throw e;
+                    }
+
+                    old_enc_sym_key = keys.get(SecureChannelProtocol.encType);
+                    old_mac_sym_key = keys.get(SecureChannelProtocol.macType);
+                    old_kek_sym_key = keys.get(SecureChannelProtocol.kekType);
+
+                    if (old_enc_sym_key == null || old_mac_sym_key == null || old_kek_sym_key == null) {
+                        throw new EBaseException(method + " Can't derive session keys with Nist KDF.");
+                    }
+
+                } else {
+                    CMS.debug(method + " ComputeSessionKey NistSP800_108KDF code: Using original KDF.");
+
+                    old_kek_sym_key = standardKDF.computeCardKey(masterKey, KDCkek, token, PROTOCOL_ONE);
+                }
+
+            }
+
+            /* special case #01#01 */
+            if (fullNewMasterKeyName != null && fullNewMasterKeyName.equals("#01#01"))
+            {
+                CMS.debug(method + " Special case dev key set for DiversifyKey!");
+
+                encKey = returnDeveloperSymKey(token, SecureChannelProtocol.encType, keySet, null);
+                macKey = returnDeveloperSymKey(token, SecureChannelProtocol.macType, keySet, null);
+                kekKey = returnDeveloperSymKey(token, SecureChannelProtocol.kekType, keySet, null);
+            } else {
+                CMS.debug(method + " Compute card key on token case ! For new key version");
+
+                if (NistSP800_108KDF.useThisKDF(nistSP800_108KdfOnKeyVersion, newKeyVersion)) {
+                    CMS.debug(method + " NistSP800_108KDF code: Using NIST SP800-108 KDF. For new key version.");
+
+                    Map<String, SymmetricKey> keys = null;
+                    try {
+                        keys = nistKDF.computeCardKeys(masterKey, context, token);
+                    } catch (EBaseException e) {
+                        CMS.debug(method + "Can't compute card keys! For new key version. " + e);
+                        throw e;
+                    }
+
+                    encKey = keys.get(SecureChannelProtocol.encType);
+                    macKey = keys.get(SecureChannelProtocol.macType);
+                    kekKey = keys.get(SecureChannelProtocol.kekType);
+
+                } else {
+                    CMS.debug(method
+                            + " ComputeSessionKey NistSP800_108KDF code: Using original KDF. For new key version.");
+
+                    encKey = standardKDF.computeCardKeyOnSoftToken(masterKey, KDCenc, protocol);
+                    macKey = standardKDF.computeCardKeyOnSoftToken(masterKey, KDCmac, protocol);
+                    kekKey = standardKDF.computeCardKeyOnSoftToken(masterKey, KDCkek, protocol);
+                }
+
+                if (encKey == null || macKey == null || kekKey == null) {
+                    throw new EBaseException(method
+                            + " Can't derive session keys with selected KDF. For new key version.");
+                }
+
+            }
+
+        } else if (protocol == PROTOCOL_TWO) {
+            throw new EBaseException(method + " SCP 02 not yet supported here.");
+        } else {
+            throw new EBaseException(method + " Unsupported protocol verison.");
+        }
+
+        boolean showKeysForDebug = false;
+
+        if (showKeysForDebug == true) {
+            try {
+                SecureChannelProtocol.debugByteArray(encKey.getKeyData(), "DiversifyKey: new encKey: ");
+                SecureChannelProtocol.debugByteArray(macKey.getKeyData(), "DiversifyKey: new macKey:");
+                SecureChannelProtocol.debugByteArray(kekKey.getKeyData(), "DiversifyKey: new kekKey");
+            } catch (NotExtractableException e) {
+                CMS.debug(method + " Can not display debugging info for key");
+            }
+        }
+
+        if (old_kek_sym_key != null) {
+
+            CMS.debug(method + " old kek sym key is not null");
+            output = createKeySetDataWithSymKeys(newKeyVersion, (byte[]) null,
+                    old_kek_sym_key,
+                    encKey,
+                    macKey,
+                    kekKey,
+                    protocol, tokenName);
+
+        } else {
+
+            CMS.debug(method + " old kek sym key is null");
+            old_kek_sym_key = returnDeveloperSymKey(token, SecureChannelProtocol.kekType, keySet, kekKeyArray);
+            output = createKeySetDataWithSymKeys(newKeyVersion, (byte[]) null,
+                    old_kek_sym_key,
+                    encKey,
+                    macKey,
+                    kekKey,
+                    protocol, tokenName);
+
+        }
+
+        return output;
+    }
+
+    private byte[] createKeySetDataWithSymKeys(byte newKeyVersion, byte[] old_kek_key_array,
+            SymmetricKey old_kek_sym_key,
+            SymmetricKey encKey, SymmetricKey macKey, SymmetricKey kekKey, byte protocol, String tokenName)
+            throws EBaseException {
+
+        SymmetricKey wrappingKey = null;
+
+        String method = "SecureChannelProtocol.createKeySetDataWithSymKeys:";
+
+        byte alg = (byte) 0x81;
+
+        byte[] output = null;
+
+        if (encKey == null || macKey == null || kekKey == null || tokenName == null) {
+            throw new EBaseException(method + " Invalid input data!");
+        }
+
+        CryptoManager cm = null;
+        CryptoToken token = null;
+        try {
+            cm = CryptoManager.getInstance();
+            token = returnTokenByName(tokenName, cm);
+        } catch (NotInitializedException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+
+        } catch (NoSuchTokenException e) {
+            CMS.debug(method + " " + e);
+            throw new EBaseException(e);
+        }
+
+        SymmetricKey encKey16 = null;
+        SymmetricKey macKey16 = null;
+        SymmetricKey kekKey16 = null;
+
+        byte[] encrypted_enc_key = null;
+        byte[] encrypted_mac_key = null;
+        byte[] encrypted_kek_key = null;
+
+        byte[] keycheck_enc_key = null;
+        byte[] keycheck_mac_key = null;
+        byte[] keycheck_kek_key = null;
+
+        if (protocol == PROTOCOL_ONE) {
+            if (old_kek_sym_key == null) {
+                CMS.debug(method + " Using old kek key array.");
+                wrappingKey = unwrapSymKeyOnToken(token, old_kek_key_array, false);
+            } else {
+                CMS.debug(method + " Using input old key key sym key.");
+                wrappingKey = old_kek_sym_key;
+            }
+
+            alg = (byte) 0x81;
+            encKey16 = extractDes2FromDes3(encKey, tokenName);
+            macKey16 = extractDes2FromDes3(macKey, tokenName);
+            kekKey16 = extractDes2FromDes3(kekKey, tokenName);
+
+            encrypted_enc_key = this.wrapSessionKey(tokenName, encKey16, wrappingKey);
+            encrypted_mac_key = this.wrapSessionKey(tokenName, macKey16, wrappingKey);
+            encrypted_kek_key = this.wrapSessionKey(tokenName, kekKey16, wrappingKey);
+
+            keycheck_enc_key = this.computeKeyCheck(encKey, tokenName);
+            keycheck_mac_key = this.computeKeyCheck(macKey, tokenName);
+            keycheck_kek_key = this.computeKeyCheck(kekKey, tokenName);
+
+            debugByteArray(keycheck_enc_key, " Keycheck enc key: ");
+            debugByteArray(keycheck_mac_key, " Keycheck mac key: ");
+            debugByteArray(keycheck_kek_key, " KeyCheck kek key: ");
+
+        } else if (protocol == PROTOCOL_TWO) {
+            alg = (byte) 0x80;
+            throw new EBaseException(method + " SCP 02 not yet implemented!");
+        } else {
+            throw new EBaseException(method + " Invalid SCP version requested!");
+        }
+
+        // Compose the final key set data byte array
+
+        byte[] b1 = new byte[] { alg, 0x10 };
+        byte[] b2 = new byte[] { 0x3 };
+
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+        try {
+            outputStream.write(newKeyVersion);
+            outputStream.write(b1);
+            outputStream.write(encrypted_enc_key);
+            outputStream.write(b2);
+            outputStream.write(keycheck_enc_key);
+
+            outputStream.write(b1);
+            outputStream.write(encrypted_mac_key);
+            outputStream.write(b2);
+            outputStream.write(keycheck_mac_key);
+
+            outputStream.write(b1);
+            outputStream.write(encrypted_kek_key);
+            outputStream.write(b2);
+            outputStream.write(keycheck_kek_key);
+
+            output = outputStream.toByteArray();
+
+        } catch (IOException e) {
+            throw new EBaseException(method + " Can't compose final output byte array!");
+        }
+
+        SecureChannelProtocol.debugByteArray(output, " Final output to createKeySetData: ");
+
+        return output;
+    }
+
+    private String getFullMasterKeyName(String masterKeyName)
+    {
+        if (masterKeyName == null)
+        {
+            return null;
+        }
+
+        String fullMasterKeyName = null;
+
+        fullMasterKeyName = "";
+
+        if (masterKeyName.length() > 0) {
+            fullMasterKeyName += masterKeyName;
+        }
+
+        return fullMasterKeyName;
+    }
+
+    private boolean checkForDeveloperKeySet(String keyInfo)
+    {
+        if (keyInfo == null)
+            return true;
+
+        //SCP01 or SCP02
+        if (keyInfo.equals("#01#01") || keyInfo.equals("#FF#01"))
+            return true;
+
+        //SCP02
+        if (keyInfo.equals("#01#02") || keyInfo.equals("#FF#02"))
+            return true;
+
+        return false;
+    }
+
+    public static void setDefaultPrefix(String masterkeyPrefix) {
+        if (SecureChannelProtocol.masterKeyPrefix == null) {
+            SecureChannelProtocol.masterKeyPrefix = masterkeyPrefix;
+        }
+    }
+
+    public byte[] encryptData(String selectedToken, String keyNickName, byte[] data, byte[] keyInfo,
+            byte nistSP800_108KdfOnKeyVersion, boolean nistSP800_108KdfUseCuidAsKdd, byte[] xCUID, byte[] xKDD,
+            byte[] kekKeyArray, String useSoftToken_s, String keySet) throws EBaseException {
+
+        String method = "SecureChannelProtocol.encryptData:";
+
+        CMS.debug(method + " Entering ....");
+
+        String transportKeyName = SecureChannelProtocol.getSharedSecretKeyName(null);
+
+        if (keyInfo == null || keySet == null || (keyInfo == null || keyInfo.length < 2)) {
+            throw new EBaseException(method + "Invalid input!");
+        }
+
+        if (xCUID == null || xCUID.length <= 0) {
+            throw new EBaseException(method + "CUID invalid size!");
+        }
+
+        if (xKDD == null || xKDD.length != NistSP800_108KDF.KDD_SIZE_BYTES) {
+            throw new EBaseException(method + "KDD invalid size!");
+        }
+
+        SymmetricKey kekKey = computeSessionKey_SCP01(kekType, selectedToken, keyNickName, null,
+                null, keyInfo, nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd, xCUID, xKDD,
+                kekKeyArray, useSoftToken_s, keySet, transportKeyName);
+
+        byte[] output = computeDes3EcbEncryption(kekKey, selectedToken, data);
+
+        debugByteArray(output, " encryptData: Output: ");
+
+        return output;
+    }
+
+}
\ No newline at end of file
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java
new file mode 100644
index 0000000..2dd145d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java
@@ -0,0 +1,170 @@
+package com.netscape.cms.servlet.tks;
+
+import java.security.InvalidKeyException;
+
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.SymmetricKeyDeriver;
+import org.mozilla.jss.crypto.TokenException;
+
+import sun.security.pkcs11.wrapper.PKCS11Constants;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
+public class StandardKDF extends KDF {
+    SecureChannelProtocol protocol = null;
+
+    StandardKDF(SecureChannelProtocol protocol) {
+        this.protocol = protocol;
+    }
+
+    public SymmetricKey computeCardKey(SymmetricKey masterKey, byte[] derivationData, CryptoToken token, int protocol)
+            throws EBaseException {
+
+        String method = "StandardKDF.computeCardKeys:";
+
+        SymmetricKey result = null;
+
+        CMS.debug(method + " entering ...");
+
+        if (masterKey == null || derivationData == null
+                || derivationData.length != SecureChannelProtocol.DES2_LENGTH || token == null) {
+
+            throw new EBaseException(method + " Invlalid input parameters!");
+        }
+
+        SymmetricKeyDeriver encryptDes3;
+        try {
+            encryptDes3 = token.getSymmetricKeyDeriver();
+
+            encryptDes3.initDerive(
+                    masterKey, /* PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA */4354L, derivationData, null,
+                    PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 16);
+
+            SymmetricKey derivedKey = encryptDes3.derive();
+
+
+            CMS.debug(method + " derived card key first 16 :" + derivedKey);
+
+            byte[] extracted = derivedKey.getEncoded();
+            SecureChannelProtocol.debugByteArray(extracted, " Derived key 16.");
+
+            long bitPosition = 0;
+
+            byte[] param = SecureChannelProtocol.longToBytes(bitPosition);
+
+            SymmetricKeyDeriver extract8 = token.getSymmetricKeyDeriver();
+            extract8.initDerive(
+                               derivedKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null,
+                               PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,8);
+
+
+           SymmetricKey extracted8 = extract8.derive();
+           CMS.debug(method + " extracted8 key: " + extracted8);
+           byte [] extracted8Bytes = extracted8.getEncoded();
+           SecureChannelProtocol.debugByteArray(extracted8Bytes, " Derived key 8.");
+
+
+           SymmetricKeyDeriver concat = token.getSymmetricKeyDeriver();
+           concat.initDerive(
+                              derivedKey,extracted8, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null,
+                              PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,0);
+
+           result =  concat.derive();
+           CMS.debug(method + " final 24 byte key: " + result);
+           byte [] extracted24Bytes = result.getEncoded();
+           SecureChannelProtocol.debugByteArray(extracted24Bytes, " Derived key 24.");
+
+        } catch (TokenException | InvalidKeyException e) {
+            CMS.debug(method + "Unable to derive the key with the proper mechanism!");
+            throw new EBaseException(e);
+        }
+
+        return result;
+
+    }
+
+    public SymmetricKey computeCardKeyOnSoftToken(SymmetricKey masterKey, byte[] data, int protocol)
+            throws EBaseException {
+        String method = "StandardKDF.computeCardKeys:";
+
+        CMS.debug(method + " entering...");
+
+        if (masterKey == null || data == null) {
+            throw new EBaseException(method + " Invlalid input parameters!");
+        }
+
+        CryptoToken token = this.protocol.getCryptoManger().getInternalKeyStorageToken();
+
+        return this.computeCardKey(masterKey, data, token, protocol);
+    }
+
+    public SymmetricKey computeCardKeyOnToken(SymmetricKey masterKey, byte[] data, int protocol) throws EBaseException {
+        String method = "StandardKDF.computeCardKeys:";
+
+        if (masterKey == null || data == null) {
+            throw new EBaseException(method + " Invlalid input parameters!");
+        }
+
+        CryptoToken token = masterKey.getOwningToken();
+
+        return this.computeCardKey(masterKey, data, token, protocol);
+    }
+
+    public byte[] getDiversificationData(byte[] context, String type) throws EBaseException {
+
+        String method = "StandardKDF.getDiversificationData:";
+
+        CMS.debug(method + " entering ...");
+
+        if (context == null || type == null) {
+            throw new EBaseException(method + "Invalid input parameters!");
+        }
+
+        byte[] KDC = new byte[SecureChannelProtocol.DES2_LENGTH];
+
+        //      BYTE *lastTwoBytesOfAID     = (BYTE *)cuidValue;
+        //      BYTE *ICFabricationDate         = (BYTE *)cuidValue + 2;
+        //      BYTE *ICSerialNumber        = (BYTE *)cuidValue + 4
+        //      BYTE *ICBatchIdentifier         = (BYTE *)cuidValue + 8;
+
+        // Last 2 bytes of AID
+        KDC[0] = context[0];
+        KDC[1] = context[1];
+        KDC[2] = context[4 + 0];
+        KDC[3] = context[4 + 1];
+        KDC[4] = context[4 + 2];
+        KDC[5] = context[4 + 3];
+        KDC[6] = (byte) 0xF0;
+        KDC[7] = 0x01;
+        KDC[8] = context[0];
+        KDC[9] = context[1];
+        KDC[10] = context[4 + 0];
+        KDC[11] = context[4 + 1];
+        KDC[12] = context[4 + 2];
+        KDC[13] = context[4 + 3];
+        KDC[14] = 0x0F;
+        KDC[15] = 0x01;
+
+        if (type.equals(SecureChannelProtocol.encType))
+            return KDC;
+
+        KDC[6] = (byte) 0xF0;
+        KDC[7] = 0x02;
+        KDC[14] = 0x0F;
+        KDC[15] = 0x02;
+        if (type.equals(SecureChannelProtocol.macType))
+            return KDC;
+
+        KDC[6] = (byte) 0xF0;
+        KDC[7] = 0x03;
+        KDC[14] = 0x0F;
+        KDC[15] = 0x03;
+        if (type.equals(SecureChannelProtocol.kekType))
+            return KDC;
+
+        return KDC;
+
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
index 83b8bef..db4cd55 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
@@ -35,6 +35,7 @@ import org.mozilla.jss.CryptoManager.NotInitializedException;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.KeyWrapAlgorithm;
 import org.mozilla.jss.crypto.KeyWrapper;
+import org.mozilla.jss.crypto.SymmetricKey;
 import org.mozilla.jss.crypto.X509Certificate;
 import org.mozilla.jss.pkcs11.PK11SymKey;
 
@@ -213,7 +214,10 @@ public class TokenServlet extends CMSServlet {
                 }
             }
 
-            SessionKey.SetDefaultPrefix(masterKeyPrefix);
+            CMS.debug("Setting masteter keky prefix to: " + masterKeyPrefix);
+
+            SecureChannelProtocol.setDefaultPrefix(masterKeyPrefix);
+            /*SessionKey.SetDefaultPrefix(masterKeyPrefix);*/
 
         } catch (Exception e) {
             e.printStackTrace();
@@ -354,7 +358,6 @@ public class TokenServlet extends CMSServlet {
 
         String rKDD = req.getParameter(IRemoteRequest.TOKEN_KDD);
 
-
         String rKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
 
         if ((rKeyInfo == null) || (rKeyInfo.equals(""))) {
@@ -561,7 +564,8 @@ public class TokenServlet extends CMSServlet {
                         selectedToken, keyNickName,
                         keyInfo,
                         nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
-                        nistSP800_108KdfUseCuidAsKdd,xCUID,xKDD, macKeyArray, sequenceCounter, derivationConstant, useSoftToken_s, keySet,
+                        nistSP800_108KdfUseCuidAsKdd, xCUID, xKDD, macKeyArray, sequenceCounter, derivationConstant,
+                        useSoftToken_s, keySet,
                         transportKeyName);
 
                 if (session_key == null) {
@@ -889,9 +893,9 @@ public class TokenServlet extends CMSServlet {
 
         boolean serversideKeygen = false;
         byte[] drm_trans_wrapped_desKey = null;
-        PK11SymKey desKey = null;
+        SymmetricKey desKey = null;
         //        PK11SymKey kek_session_key;
-        PK11SymKey kek_key;
+        SymmetricKey kek_key;
 
         IConfigStore sconfig = CMS.getConfigStore();
         boolean isCryptoValidate = true;
@@ -1092,14 +1096,15 @@ public class TokenServlet extends CMSServlet {
                                     + keySet + ".mac_key"));
                     CMS.debug("TokenServlet about to try ComputeSessionKey selectedToken="
                             + selectedToken + " keyNickName=" + keyNickName);
-                    session_key = SessionKey.ComputeSessionKey(
-                            selectedToken, keyNickName, card_challenge,
-                            host_challenge, keyInfo,
-                            nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
-                            xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
-                            macKeyArray, useSoftToken_s, keySet, transportKeyName);
+
+                    SecureChannelProtocol protocol = new SecureChannelProtocol();
+                    SymmetricKey macKey = protocol.computeSessionKey_SCP01(SecureChannelProtocol.macType,
+                            selectedToken,
+                            keyNickName, card_challenge,
+                            host_challenge, keyInfo, nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd, xCUID,
+                            xKDD, macKeyArray, useSoftToken_s, keySet, transportKeyName);
+
+                    session_key = protocol.wrapSessionKey(selectedToken, macKey, null);
 
                     if (session_key == null) {
                         CMS.debug("TokenServlet:Tried ComputeSessionKey, got NULL ");
@@ -1110,14 +1115,13 @@ public class TokenServlet extends CMSServlet {
                     byte encKeyArray[] =
                             com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
                                     + keySet + ".auth_key"));
-                    enc_session_key = SessionKey.ComputeEncSessionKey(
-                            selectedToken, keyNickName, card_challenge,
-                            host_challenge, keyInfo,
-                            nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
-                            xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
-                            encKeyArray, useSoftToken_s, keySet);
+                    SymmetricKey encKey = protocol.computeSessionKey_SCP01(SecureChannelProtocol.encType,
+                            selectedToken,
+                            keyNickName, card_challenge, host_challenge, keyInfo, nistSP800_108KdfOnKeyVersion,
+                            nistSP800_108KdfUseCuidAsKdd, xCUID, xKDD, encKeyArray, useSoftToken_s, keySet,
+                            transportKeyName);
+
+                    enc_session_key = protocol.wrapSessionKey(selectedToken, encKey, null);
 
                     if (enc_session_key == null) {
                         CMS.debug("TokenServlet:Tried ComputeEncSessionKey, got NULL ");
@@ -1140,14 +1144,11 @@ public class TokenServlet extends CMSServlet {
                                 com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
                                         + keySet + ".kek_key"));
 
-                        kek_key = SessionKey.ComputeKekKey(
-                                selectedToken, keyNickName, card_challenge,
-                                host_challenge, keyInfo,
-                                nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
-                                nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
-                                xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
-                                xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
-                                kekKeyArray, useSoftToken_s, keySet);
+                        kek_key = protocol.computeSessionKey_SCP01(SecureChannelProtocol.kekType, selectedToken,
+                                keyNickName, card_challenge,
+                                host_challenge, keyInfo, nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd,
+                                xCUID,
+                                xKDD, kekKeyArray, useSoftToken_s, keySet, transportKeyName);
 
                         CMS.debug("TokenServlet: called ComputeKekKey");
 
@@ -1177,11 +1178,12 @@ public class TokenServlet extends CMSServlet {
                         if (useSoftToken_s.equals("true")) {
                             CMS.debug("TokenServlet: key encryption key generated on internal");
                             //cfu audit here? sym key gen
-                            desKey = SessionKey.GenerateSymkey("internal");
+
+                            desKey = protocol.generateSymKey("internal");
                             //cfu audit here? sym key gen done
                         } else {
                             CMS.debug("TokenServlet: key encryption key generated on " + selectedToken);
-                            desKey = SessionKey.GenerateSymkey(selectedToken);
+                            desKey = protocol.generateSymKey(selectedToken);
                         }
                         if (desKey != null) {
                             // AC: KDF SPEC CHANGE - Output using CUID and KDD
@@ -1204,9 +1206,9 @@ public class TokenServlet extends CMSServlet {
                          * and discard the last 8 bytes before it encrypts.
                          * This is done so that the applet can digest it
                          */
-                        byte[] encDesKey =
-                                SessionKey.ECBencrypt(kek_key,
-                                        desKey);
+
+                        byte[] encDesKey = protocol.ecbEncrypt(kek_key, desKey, selectedToken);
+
                         /*
                         CMS.debug("computeSessionKey:encrypted desKey size = "+encDesKey.length);
                         CMS.debug(encDesKey);
@@ -1216,8 +1218,8 @@ public class TokenServlet extends CMSServlet {
                                 com.netscape.cmsutil.util.Utils.SpecialEncode(encDesKey);
 
                         // get keycheck
-                        byte[] keycheck =
-                                SessionKey.ComputeKeyCheck(desKey);
+
+                        byte[] keycheck = protocol.computeKeyCheck(desKey, selectedToken);
                         /*
                         CMS.debug("computeSessionKey:keycheck size = "+keycheck.length);
                         CMS.debug(keycheck);
@@ -1266,28 +1268,21 @@ public class TokenServlet extends CMSServlet {
                     byte authKeyArray[] =
                             com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
                                     + keySet + ".auth_key"));
-                    host_cryptogram = SessionKey.ComputeCryptogram(
-                            selectedToken, keyNickName, card_challenge,
-                            host_challenge, keyInfo,
-                            nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
-                            xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
-                            0, authKeyArray, useSoftToken_s, keySet);
+
+                    host_cryptogram = protocol.computeCryptogram_SCP01(selectedToken, keyNickName, card_challenge,
+                            host_challenge,
+                            xkeyInfo, nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd, xCUID, xKDD, 0,
+                            authKeyArray, useSoftToken_s, keySet, transportKeyName);
 
                     if (host_cryptogram == null) {
                         CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL ");
                         throw new Exception("Can't compute host cryptogram!");
 
                     }
-                    card_crypto = SessionKey.ComputeCryptogram(
-                            selectedToken, keyNickName, card_challenge,
-                            host_challenge, keyInfo,
-                            nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
-                            xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
-                            xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
-                            1, authKeyArray, useSoftToken_s, keySet);
+
+                    card_crypto = protocol.computeCryptogram_SCP01(selectedToken, keyNickName, card_challenge,
+                            host_challenge, xkeyInfo, nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd,
+                            xCUID, xKDD, 1, authKeyArray, useSoftToken_s, keySet, transportKeyName);
 
                     if (card_crypto == null) {
                         CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL ");
@@ -1302,6 +1297,10 @@ public class TokenServlet extends CMSServlet {
                         }
                         input_card_crypto =
                                 com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_cryptogram);
+
+                        SecureChannelProtocol.debugByteArray(input_card_crypto, "input_card_crypto");
+                        SecureChannelProtocol.debugByteArray(card_crypto, "card_crypto");
+
                         if (card_crypto.length == input_card_crypto.length) {
                             for (int i = 0; i < card_crypto.length; i++) {
                                 if (card_crypto[i] != input_card_crypto[i]) {
@@ -1782,18 +1781,28 @@ public class TokenServlet extends CMSServlet {
             byte kekKeyArray[] =
                     com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
 
+            SecureChannelProtocol secProtocol = new SecureChannelProtocol();
             // AC: KDF SPEC CHANGE - check for error reading settings
             if (missingSetting_exception == null) {
-                KeySetData = SessionKey.DiversifyKey(oldSelectedToken,
-                        newSelectedToken, oldKeyNickName,
-                        newKeyNickName,
-                        xkeyInfo, // AC: KDF SPEC CHANGE - pass in old key info so symkey can make decision about which KDF version to use
-                        xnewkeyInfo, // AC: BUGFIX for key versions higher than 09:  We need to specialDecode keyInfo parameters before sending them into symkey!  This means the parameters must be byte[]
-                        nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
-                        nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
-                        xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
-                        xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
-                        (protocol == 2) ? xWrappedDekKey : kekKeyArray, useSoftToken_s, keySet, (byte) protocol);
+                if (protocol == 1) {
+                    KeySetData = secProtocol.diversifyKey(oldSelectedToken,
+                            newSelectedToken, oldKeyNickName,
+                            newKeyNickName,
+                            xkeyInfo, // AC: KDF SPEC CHANGE - pass in old key info so symkey can make decision about which KDF version to use
+                            xnewkeyInfo, // AC: BUGFIX for key versions higher than 09:  We need to specialDecode keyInfo parameters before sending them into symkey!  This means the parameters must be byte[]
+                            nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+                            nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+                            xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+                            xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+                            (protocol == 2) ? xWrappedDekKey : kekKeyArray, useSoftToken_s, keySet, (byte) protocol);
+
+                } else if (protocol == 2) {
+                    KeySetData = SessionKey.DiversifyKey(oldSelectedToken, newSelectedToken, oldKeyNickName,
+                            newKeyNickName, xkeyInfo,
+                            xnewkeyInfo, nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd, xCUID, xKDD,
+                            (protocol == 2) ? xWrappedDekKey : kekKeyArray, useSoftToken_s, keySet, (byte) protocol);
+                }
+                SecureChannelProtocol.debugByteArray(KeySetData, " New keyset data: ");
 
                 if (KeySetData == null || KeySetData.length <= 1) {
                     CMS.getLogger().log(ILogger.EV_AUDIT,
@@ -1817,7 +1826,6 @@ public class TokenServlet extends CMSServlet {
 
         } // ! missingParam
 
-
         String value = "";
         String status = "0";
 
@@ -2092,7 +2100,9 @@ public class TokenServlet extends CMSServlet {
             // AC: KDF SPEC CHANGE - check for error reading settings
             if (missingSetting_exception == null) {
 
-                encryptedData = SessionKey.EncryptData(
+                SecureChannelProtocol protocol = new SecureChannelProtocol();
+
+                encryptedData = protocol.encryptData(
                         selectedToken, keyNickName, data, keyInfo,
                         nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
                         nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
@@ -2100,6 +2110,8 @@ public class TokenServlet extends CMSServlet {
                         xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
                         kekKeyArray, useSoftToken_s, keySet);
 
+                SecureChannelProtocol.debugByteArray(encryptedData, "New Encrypt Data: ");
+
                 // AC: KDF SPEC CHANGE - Log both CUID and KDD
 
                 CMS.getLogger().log(ILogger.EV_AUDIT,
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index 01cde76..ed762c8 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -33,6 +33,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import netscape.security.x509.RevocationReason;
+
 import org.dogtagpki.server.tps.TPSSession;
 import org.dogtagpki.server.tps.TPSSubsystem;
 import org.dogtagpki.server.tps.authentication.AuthUIParameter;
@@ -77,7 +79,10 @@ import org.dogtagpki.tps.msg.StatusUpdateRequestMsg;
 import org.dogtagpki.tps.msg.TPSMessage;
 import org.dogtagpki.tps.msg.TokenPDURequestMsg;
 import org.dogtagpki.tps.msg.TokenPDUResponseMsg;
+import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SymmetricKey;
 import org.mozilla.jss.pkcs11.PK11SymKey;
 
 import com.netscape.certsrv.apps.CMS;
@@ -90,10 +95,9 @@ import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.common.Constants;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.tps.token.TokenStatus;
+import com.netscape.cms.servlet.tks.SecureChannelProtocol;
 import com.netscape.symkey.SessionKey;
 
-import netscape.security.x509.RevocationReason;
-
 public class TPSProcessor {
 
     public static final int RESULT_NO_ERROR = 0;
@@ -598,7 +602,7 @@ public class TPSProcessor {
         PK11SymKey cmacSessionKeySCP02 = null;
         PK11SymKey rmacSessionKeySCP02 = null;
 
-        PK11SymKey sharedSecret = null;
+        SymmetricKey sharedSecret = null;
 
         //Sanity checking
 
@@ -624,16 +628,30 @@ public class TPSProcessor {
                     TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
         }
 
+        SecureChannelProtocol protocol = new SecureChannelProtocol();
+
+        String tokenName = "Internal Key Storage Token";
+
+        CryptoManager cm = null;
+        CryptoToken token = null;
+
+        String sharedSecretName = null;
         try {
-            sharedSecret = getSharedSecretTransportKey(connId);
+            sharedSecretName = getSharedSecretTransportKeyName(connId);
+            SecureChannelProtocol.setSharedSecretKeyName(sharedSecretName);
+
+            cm = protocol.getCryptoManger();
+            token = protocol.returnTokenByName(tokenName, cm);
+
+            sharedSecret = SecureChannelProtocol.getSymKeyByName(token, sharedSecretName);
+
+            // 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);
         }
 
-        String tokenName = "Internal Key Storage Token";
-
         if (platProtInfo.isGP201() || platProtInfo.isSCP01()) {
 
             resp = engine.computeSessionKey(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
@@ -652,18 +670,28 @@ public class TPSProcessor {
                 TPSBuffer sessionKeyWrapped = resp.getSessionKey();
                 TPSBuffer encSessionKeyWrapped = resp.getEncSessionKey();
 
-                sessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
-                        sessionKeyWrapped.toBytesArray());
+             /* sessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, (PK11SymKey) sharedSecret,
+                        sessionKeyWrapped.toBytesArray()); */
+
+
+               sessionKey =  (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret, sessionKeyWrapped.toBytesArray(), false);
+
+
+
+
 
                 if (sessionKey == null) {
                     CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!");
                     throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract session key!",
                             TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
                 }
+
                 CMS.debug("TPSProcessor.generateSecureChannel: retrieved session key: " + sessionKey);
 
-                encSessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
-                        encSessionKeyWrapped.toBytesArray());
+              /*  encSessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName,(PK11SymKey) sharedSecret,
+                        encSessionKeyWrapped.toBytesArray()); */
+
+                encSessionKey = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret,encSessionKeyWrapped.toBytesArray(),false);
 
                 if (encSessionKey == null) {
                     CMS.debug("TPSProcessor.generateSecureChannel: Can't extract enc session key!");
@@ -716,7 +744,7 @@ public class TPSProcessor {
                     connId, getSelectedTokenType(), getSelectedKeySet());
 
             TPSBuffer encSessionKeyWrappedSCP02 = respEnc02.getSessionKey();
-            encSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+            encSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, (PK11SymKey) sharedSecret,
                     encSessionKeyWrappedSCP02.toBytesArray());
 
             if (encSessionKeySCP02 == null) {
@@ -731,7 +759,7 @@ public class TPSProcessor {
 
             TPSBuffer cmacSessionKeyWrappedSCP02 = respCMac02.getSessionKey();
 
-            cmacSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+            cmacSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName,(PK11SymKey) sharedSecret,
                     cmacSessionKeyWrappedSCP02.toBytesArray());
 
             if (cmacSessionKeySCP02 == null) {
@@ -746,7 +774,7 @@ public class TPSProcessor {
 
             TPSBuffer rmacSessionKeyWrappedSCP02 = respRMac02.getSessionKey();
 
-            rmacSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+            rmacSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName,(PK11SymKey) sharedSecret,
                     rmacSessionKeyWrappedSCP02.toBytesArray());
 
             if (rmacSessionKeySCP02 == null) {
@@ -763,7 +791,7 @@ public class TPSProcessor {
 
             TPSBuffer dekSessionKeyWrappedSCP02 = respDek02.getSessionKey();
 
-            dekSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+            dekSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName,(PK11SymKey) sharedSecret,
                     dekSessionKeyWrappedSCP02.toBytesArray());
 
             if (dekSessionKeySCP02 == null) {
@@ -2714,7 +2742,7 @@ public class TPSProcessor {
 
     }
 
-    protected PK11SymKey getSharedSecretTransportKey(String connId) throws TPSException, NotInitializedException {
+    protected String getSharedSecretTransportKeyName(String connId) throws TPSException {
 
         IConfigStore configStore = CMS.getConfigStore();
         String sharedSecretName = null;
@@ -2729,10 +2757,21 @@ public class TPSProcessor {
 
         }
 
+        CMS.debug("TPSProcessor.getSharedSecretTransportKeyName: calculated key name: " + sharedSecretName);
+
+        return sharedSecretName;
+
+    }
+    protected PK11SymKey getSharedSecretTransportKey(String connId) throws TPSException, NotInitializedException {
+
+
+        String sharedSecretName = getSharedSecretTransportKeyName(connId);
+
         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);
@@ -2878,7 +2917,7 @@ public class TPSProcessor {
         result.setFreeMem(free_mem);
 
         CMS.debug("TPSProcessor.getAppletInfo: cuid: " + result.getCUIDhexString() + " msn: " + result.getMSNString()
-                + " major version: " + result.getMinorVersion() + " minor version: " + result.getMinorVersion()
+                + " major version: " + result.getMajorVersion() + " minor version: " + result.getMinorVersion()
                 + " App major version: " + result.getAppMajorVersion() + " App minor version: "
                 + result.getAppMinorVersion());
 
@@ -3269,14 +3308,15 @@ public class TPSProcessor {
          * In the mean time, resolution is to save up the result the first
          *  time it is called
          */
-        if (aInfo.getFinalAppletVersion() != null) {
-            return aInfo.getFinalAppletVersion();
-        }
 
         if (aInfo == null) {
             throw new TPSException("TPSProcessor.formatCurrentAppletVersion: ", TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
         }
 
+        if (aInfo.getFinalAppletVersion() != null) {
+            return aInfo.getFinalAppletVersion();
+        }
+
         TPSBuffer build_id = getAppletVersion();
         if (build_id == null) {
             CMS.debug(method + " getAppletVersion returning null");
@@ -3284,7 +3324,7 @@ public class TPSProcessor {
         }
         String build_idStr = build_id.toHexStringPlain();
 
-        String finalVersion = aInfo.getAppMajorVersion() + "." + aInfo.getAppMinorVersion() + "." + build_idStr;
+        String finalVersion = aInfo.getMajorVersion() + "." + aInfo.getMinorVersion() + "." + build_idStr;
 
         finalVersion = finalVersion.toLowerCase();
 
@@ -3852,6 +3892,7 @@ public class TPSProcessor {
             String status,
             String info) {
         String auditType = "LOGGING_SIGNED_AUDIT_TOKEN_OP_REQUEST_6";
+
         String auditMessage = CMS.getLogMessage(
                 auditType,
                 session.getIpAddress(),
@@ -3952,7 +3993,7 @@ public class TPSProcessor {
         String auditType = "";
         switch (status) {
         case "success":
-            auditType = "LOGGING_SIGNED_AUDIT_TOKEN_KEY_CHANGEOVER_SUCCESS_9";
+            auditType = "LOGGING_SIGNED_AUDIT_TOKEN_KEY_CHANGEOVER_SUCCESS_10";
             break;
         default:
             auditType = "LOGGING_SIGNED_AUDIT_TOKEN_KEY_CHANGEOVER_FAILURE_10";
-- 
2.5.0

