[Pki-devel] [pki-devel][PATCH] 0064-Port-symkey-JNI-to-Java-classes.patch

Fraser Tweedale ftweedal at redhat.com
Sun Apr 17 23:37:45 UTC 2016


On Fri, Apr 15, 2016 at 10:03:03PM -0400, John Magne wrote:
> 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.
> 
Are you going to rebase to a new version of JSS (i.e. 4.3.x) or
apply more patches on 4.2.6?  There is a feature unavailable in
4.2.6 that I'd like to get into the next release of JSS as well.

> 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.

> From e4b02023290624b899192f65626f0c0f60d5638c Mon Sep 17 00:00:00 2001
> From: Jack Magne <jmagne at 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
> 

> _______________________________________________
> Pki-devel mailing list
> Pki-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/pki-devel




More information about the Pki-devel mailing list