/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */


#include "pkcsprivate.h"

extern CSSM_SPI_MEMORY_FUNCS  CssmMemFuncs;
extern CSSM_GUID CssmGuid;


/*****************************************************************************
 * Function: SetDesParity 
 * 
 * Set a DES/3DES key parity bits to odd parity, low bit is parity bit.  
 *
 * Input:
 *  pCssmData     - DES/3DES key data
 *
 * Output:
 *  pCssmData     - DES/3DES key data with parity bits correctly set
 *
 * Returns:
 *  None
 *
 */

void SetDesParity(CSSM_DATA_PTR pCssmData)
{
  uint8 ii;
  uint8 bitCount;
  uint8 byte;


  if (pCssmData == NULL || pCssmData->Data == NULL)
    return;

  for (ii = 0; ii < pCssmData->Length; ii++)
  {
    bitCount = 0;
    byte = *(pCssmData->Data + ii);

    if (byte & 0x80)
      bitCount++;
    if (byte & 0x40)
      bitCount++;
    if (byte & 0x20)
      bitCount++;
    if (byte & 0x10)
      bitCount++;
    if (byte & 0x08)
      bitCount++;
    if (byte & 0x04)
      bitCount++;
    if (byte & 0x02)
      bitCount++;
    
    if ((bitCount % 2) == 0)  // even
      byte |= 0x01;     // turn parity bit on
    else            // odd
      byte &= 0xFE;     // turn parity bit off
    
    *(pCssmData->Data + ii) = byte;
  }
}



/*****************************************************************************
 * Function: DataInsert 
 * 
 * Insert a record or key into token  
 *
 * Input:
 *  CssmDLDBHandle    - DL/DB handles 
 *  CssmRecordType    - Record type
 *  pCssmAttributes   - Record attributes
 *  pCssmData     - Record data, currently only keys are supported
 *
 * Output:
 *  None
 *
 * Returns:
 *  CSSM_DB_UNIQUE_RECORD_PTR - Successful      
 *  NULL            - Failed
 *
 */

CSSM_DB_UNIQUE_RECORD_PTR CSSMAPI DataInsert (
    CSSM_DL_DB_HANDLE CssmDLDBHandle,
    const CSSM_DB_RECORDTYPE CssmRecordType,
    const CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pCssmAttributes, 
    const CSSM_DATA_PTR pCssmData)
{
  MSMSESSION_PTR        pMsmSession;

  CSSM_DB_UNIQUE_RECORD_PTR pCssmUniqueRecord;
  CSSM_KEY_PTR        pCssmInKey;
  CSSM_KEYHEADER_PTR      pCssmInHeader;
  CSSM_RSA_PUBLIC_PTR     pCssmRsaPublic;
  CSSM_DSA_PUBLIC_PTR     pCssmDsaPublic;
  CSSM_DH_PUBLIC_PTR      pCssmDhPublic;

  CK_RV           PkcsRc;
  CK_RV           PkcsSavedRc;
  CK_ATTRIBUTE_PTR      pPkcsTemplate;
  CK_OBJECT_HANDLE      hPkcsObject;


//
//  Common Key Data
//

// Common Object Attrs  
  CK_OBJECT_CLASS       PkcsClass;        // Required
  CK_BBOOL          PkcsToken;        // FALSE
  CK_BBOOL          PkcsPrivate;      // FALSE
#ifdef PKCS11_V20
  CK_BBOOL          PkcsModifiable;     // TRUE
#endif
//  CK_CHAR_PTR         pPkcsObjectLabel;   // NULL, not used by CDSA

// Common Key Attrs
  CK_KEY_TYPE         PkcsKeyType;      // Required
//  CK_CHAR_PTR         pPkcsId;        // NULL
//  CK_DATE           PkcsStartDate;      // Empty
//  CK_DATE           PkcsEndDate;      // Empty
  CK_BBOOL          PkcsDerive;       // FALSE
//  CK_BBOOL          PkcsLocal;        // Not setable


//
//  Secret Key Data
//

  CK_BBOOL          PkcsSessionSensitive;   // FALSE
  CK_BBOOL          PkcsSessionEncrypt;     // Token default
  CK_BBOOL          PkcsSessionDecrypt;     // Token default
  CK_BBOOL          PkcsSessionSign;      // Token default
  CK_BBOOL          PkcsSessionVerify;      // Token default
  CK_BBOOL          PkcsSessionWrap;      // Token default
  CK_BBOOL          PkcsSessionUnwrap;      // Token default
//  CK_BBOOL          PkcsSessionExtractable;   // Token default
//  CK_BBOOL          PkcsSessionAlwaysSensitive; // Not setable
//  CK_BBOOL          PkcsSessionNeverExtractable;// Not setable
//  CK_CHAR_PTR         pPkcsSessionValue;      // Not setable
#ifdef PKCS11_V20
  CK_ULONG          PkcsSessionValueLen;    // Required when variable
#else
  CK_USHORT         PkcsSessionValueLen;    // Required when variable
#endif
//
//  Public Key Data
//

// Common Public Key Attrs
//  CK_CHAR_PTR         pPkcsPublicSubject;     // Empty, not used by CDSA
  CK_BBOOL          PkcsPublicEncrypt;      // Token default
  CK_BBOOL          PkcsPublicVerify;     // Token default/
  CK_BBOOL          PkcsPublicVerifyRecover;  // Token default
  CK_BBOOL          PkcsPublicWrap;       // Token default

// RSA Specific Attrs
//  CK_BYTE_PTR         pPkcsPublicModulus;     // Supplied by C_GenerateKeyPair
//  CK_ULONG          PkcsPublicModulusBits;    // Required
//  CK_BYTE_PTR         pPkcsPublicPublicExponent;  // Required


// DSA, ECDSA, DH, KEA, MAYFLY Specific Attrs
//  CK_BYTE_PTR         pPkcsPublicPrime;     // Required
//  CK_BYTE_PTR         pPkcsPublicSubPrime;    // Required except by DH
//  CK_BYTE_PTR         pPkcsPublicBase;      // Required
//  CK_BYTE_PTR         pPkcsPublicValue;     // Supplied by C_GenerateKeyPair


//
//  Private Key Data
//

// Common Private Key Attrs 
//  CK_CHAR_PTR         pPkcsPrivateSubject;    // Empty, not used by CDSA
//  CK_BBOOL          PkcsPrivateSensitive;   // FALSE
//  CK_BBOOL          PkcsPrivateDecrypt;     // Token default
//  CK_BBOOL          PkcsPrivateSign;      // Token default
//  CK_BBOOL          PkcsPrivateSignRecover;   // Token default
//  CK_BBOOL          PkcsPrivateUnwrap;      // Token default
//  CK_BBOOL          PkcsPrivateExtractable;   // Token default
//  CK_BBOOL          PkcsPrivateAlwaysSensitive; // Not setable
//  CK_BBOOL          PkcsPrivateNeverExtractable;// Not setable

// RSA Specific Attrs
//  CK_BYTE_PTR         pPkcsPrivateModulus;    // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivatePublicExponent; // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivatePrivateExponent;// Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivatePrime_1;    // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivatePrime_2;    // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivateExponent_1;   // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivateExponent_2;   // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivateCoefficient;  // Supplied by C_GenerateKeyPair

// DSA, ECDSA, DH, KEA, MAYFLY Specific Attrs
//  CK_BYTE_PTR         pPkcsPrivatePrime;      // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivateSubPrime;   // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivateBase;     // Supplied by C_GenerateKeyPair
//  CK_BYTE_PTR         pPkcsPrivateValue;      // Supplied by C_GenerateKeyPair
//  CK_ULONG          PkcsPrivateValueBits    // Supplied by C_GenerateKeyPair


  CK_ATTRIBUTE        PkcsTemplate[PKCS_TOTAL_PRIVATE_ATTRS];

#ifdef PKCS11_V20
  CK_ULONG          ii = 0;
#else
  CK_USHORT         ii = 0;
#endif

  CSSM_BOOL         bValueLenNeeded = CSSM_FALSE;     



  if ((pMsmSession = FindMsmSession(CssmDLDBHandle.DLHandle)) != NULL)
  {
    if (CssmDLDBHandle.DBHandle != pMsmSession->CssmHandleInfo.SubServiceID)
      return SetErrNull(CSSM_DL_INVALID_DB_HANDLE);

    if (pCssmAttributes != NULL && pCssmData == NULL)
    {
      if (CssmRecordType != CSSM_DL_DB_RECORD_PUBLIC_KEY &&
        CssmRecordType != CSSM_DL_DB_RECORD_PRIVATE_KEY &&
        CssmRecordType != CSSM_DL_DB_RECORD_SYMMETRIC_KEY &&
        CssmRecordType != CSSM_DL_DB_RECORD_CERT &&
        CssmRecordType != CSSM_DL_DB_RECORD_GENERIC)
        return SetErrNull(CSSM_DL_INVALID_RECORD_TYPE);

      if ((pPkcsTemplate = (CK_ATTRIBUTE_PTR) calloc(pCssmAttributes->NumberOfAttributes, 
                               sizeof(CK_ATTRIBUTE))) == NULL)
      {
        return SetErrNull(CSSM_DL_MEMORY_ERROR);
      }
      else
      {
        for (ii = 0; ii < pCssmAttributes->NumberOfAttributes; ii++)
        {
          if ((pCssmAttributes->AttributeData + ii)->Info.AttributeNameFormat != 
                                    CSSM_DB_ATTRIBUTE_NAME_AS_NUMBER)
          {
            free(pPkcsTemplate);
            return SetErrNull(CSSM_DL_INVALID_ATTRIBUTE_NAME_FORMAT);
          }
          (pPkcsTemplate + ii)->type = (pCssmAttributes->AttributeData + ii)->Info.AttributeNumber;
          (pPkcsTemplate + ii)->pValue = (CK_VOID_PTR) (pCssmAttributes->AttributeData + ii)->Value.Data;
  #ifdef PKCS11_V20
          (pPkcsTemplate + ii)->ulValueLen = (pCssmAttributes->AttributeData + ii)->Value.Length;
  #else
          (pPkcsTemplate + ii)->usValueLen = (pCssmAttributes->AttributeData + ii)->Value.Length;
  #endif
        }

  #ifdef PKCS11_V20
        if ((PkcsRc = C_CreateObject(pMsmSession->PkcsSessionHandle,
                       pPkcsTemplate,
                       pCssmAttributes->NumberOfAttributes,
                       &hPkcsObject)) == CKR_OK)
  #else
        if ((PkcsRc = C_CreateObject(pMsmSession->PkcsSessionHandle,
                       pPkcsTemplate,
                       (USHORT) pCssmAttributes->NumberOfAttributes,
                       &hPkcsObject)) == CKR_OK)
  #endif
        {
          if ((pCssmUniqueRecord = CssmMemFuncs.calloc_func(pMsmSession->CssmModuleHandle, 
                                    1, 
                                    sizeof(CSSM_DB_UNIQUE_RECORD))) == NULL)
          {
            free(pPkcsTemplate);
            return SetErrNull(CSSM_DL_MEMORY_ERROR);
          }

          if ((pCssmUniqueRecord->RecordIdentifier.Data = CssmMemFuncs.calloc_func(
                                    pMsmSession->CssmModuleHandle, 
                                    1, 
                                    sizeof(CK_OBJECT_HANDLE))) == NULL)
          {
            free(pCssmUniqueRecord);
            free(pPkcsTemplate);
            return SetErrNull(CSSM_DL_MEMORY_ERROR);
          }

          *((CK_OBJECT_HANDLE_PTR) pCssmUniqueRecord->RecordIdentifier.Data) = hPkcsObject;
          pCssmUniqueRecord->RecordIdentifier.Length = sizeof(CK_OBJECT_HANDLE);

          free(pPkcsTemplate);
          return pCssmUniqueRecord;
        }
        else
        {
          free(pPkcsTemplate);
          return SetErrNull(PkcsRc);
        }
      }
    }
    else if (pCssmAttributes == NULL && pCssmData != NULL)
    {
      if (CssmRecordType != CSSM_DL_DB_RECORD_PUBLIC_KEY &&
          CssmRecordType != CSSM_DL_DB_RECORD_PRIVATE_KEY &&
          CssmRecordType != CSSM_DL_DB_RECORD_SYMMETRIC_KEY)
        return SetErrNull(CSSM_DL_INVALID_RECORD_TYPE);

      if (pCssmData->Data != NULL)
      {
        pCssmInKey = (CSSM_KEY_PTR) pCssmData->Data;
        pCssmInHeader = &pCssmInKey->KeyHeader;
printf("pCssmInHeader->BlobType = %d\n", pCssmInHeader->BlobType);
printf("Format = %d\n", pCssmInHeader->Format);
printf("KeyClass = %d\n", pCssmInHeader->KeyClass);
        if (pCssmInHeader->BlobType != CSSM_KEYBLOB_RAW ||
          pCssmInHeader->Format != CSSM_KEYBLOB_RAW_FORMAT_CDSA ||
          (pCssmInHeader->KeyClass != CSSM_KEYCLASS_SESSION_KEY &&
           pCssmInHeader->KeyClass != CSSM_KEYCLASS_PUBLIC_KEY))
        {
printf("Damn!\n");
           return SetErrNull(CSSM_CSP_INVALID_KEY);
        }

        PkcsTemplate[ii].type = CKA_START_DATE;
        PkcsTemplate[ii].pValue = &pCssmInHeader->StartDate;
#ifdef PKCS11_V20
        PkcsTemplate[ii++].ulValueLen = sizeof(CSSM_DATE);
#else
        PkcsTemplate[ii++].usValueLen = sizeof(CSSM_DATE);
#endif

        PkcsTemplate[ii].type = CKA_END_DATE;
        PkcsTemplate[ii].pValue = &pCssmInHeader->EndDate;
#ifdef PKCS11_V20
        PkcsTemplate[ii++].ulValueLen = sizeof(CSSM_DATE);
#else
        PkcsTemplate[ii++].usValueLen = sizeof(CSSM_DATE);
#endif

        if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
          (pCssmInHeader->KeyUsage & CSSM_KEYUSE_DERIVE))
          PkcsDerive = TRUE;
        else
          PkcsDerive = FALSE;

        PkcsTemplate[ii].type = CKA_DERIVE;
        PkcsTemplate[ii].pValue = &PkcsDerive;
#ifdef PKCS11_V20
        PkcsTemplate[ii++].ulValueLen = sizeof(PkcsDerive);
#else
        PkcsTemplate[ii++].usValueLen = sizeof(PkcsDerive);
#endif  
          
        if (pCssmInHeader->KeyAttr & CSSM_KEYATTR_PERMANENT)
          PkcsToken = TRUE;
        else
          PkcsToken = FALSE;
            
        PkcsTemplate[ii].type = CKA_TOKEN;
        PkcsTemplate[ii].pValue = &PkcsToken;
#ifdef PKCS11_V20
        PkcsTemplate[ii++].ulValueLen = sizeof(PkcsToken);
#else
        PkcsTemplate[ii++].usValueLen = sizeof(PkcsToken);
#endif  

        if (pCssmInHeader->KeyAttr & CSSM_KEYATTR_PRIVATE)
          PkcsPrivate = TRUE;
        else
          PkcsPrivate = FALSE;
          
        PkcsTemplate[ii].type = CKA_PRIVATE;
        PkcsTemplate[ii].pValue = &PkcsPrivate;
#ifdef PKCS11_V20
        PkcsTemplate[ii++].ulValueLen = sizeof(PkcsPrivate);
#else
        PkcsTemplate[ii++].usValueLen = sizeof(PkcsPrivate);
#endif  


#ifdef PKCS11_V20
        if (pCssmInHeader->KeyAttr & CSSM_KEYATTR_MODIFIABLE)
          PkcsModifiable = TRUE;
        else
          PkcsModifiable = FALSE;
            
        PkcsTemplate[ii].type = CKA_MODIFIABLE;
        PkcsTemplate[ii].pValue = &PkcsModifiable;
        PkcsTemplate[ii++].ulValueLen = sizeof(PkcsModifiable);
#endif

        if (pCssmInHeader->KeyClass == CSSM_KEYCLASS_PUBLIC_KEY)
        {
          PkcsClass = CKO_PUBLIC_KEY;
          PkcsTemplate[ii].type = CKA_CLASS;
          PkcsTemplate[ii].pValue = &PkcsClass;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsClass);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsClass);
#endif  

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_ENCRYPT))
            PkcsPublicEncrypt = TRUE;
          else
            PkcsPublicEncrypt = FALSE;

          PkcsTemplate[ii].type = CKA_ENCRYPT;
          PkcsTemplate[ii].pValue = &PkcsPublicEncrypt;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsPublicEncrypt);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsPublicEncrypt);
#endif  

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_VERIFY))
            PkcsPublicVerify = TRUE;
          else
            PkcsPublicVerify = FALSE;
        
          PkcsTemplate[ii].type = CKA_VERIFY;
          PkcsTemplate[ii].pValue = &PkcsPublicVerify;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsPublicVerify);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsPublicVerify);
#endif  

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_VERIFY_RECOVER))
            PkcsPublicVerifyRecover = TRUE;
          else
            PkcsPublicVerifyRecover = FALSE;

          PkcsTemplate[ii].type = CKA_VERIFY_RECOVER;
          PkcsTemplate[ii].pValue = &PkcsPublicVerifyRecover;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsPublicVerifyRecover);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsPublicVerifyRecover);
#endif  

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_WRAP))
            PkcsPublicWrap = TRUE;
          else
            PkcsPublicWrap = FALSE;
        
          PkcsTemplate[ii].type = CKA_WRAP;
          PkcsTemplate[ii].pValue = &PkcsPublicWrap;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsPublicWrap);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsPublicWrap);
#endif

          switch (pCssmInHeader->AlgorithmId)
          {
            case CSSM_ALGID_RSA_PKCS:
              PkcsKeyType = CKK_RSA;
              PkcsTemplate[ii].type = CKA_KEY_TYPE;
              PkcsTemplate[ii].pValue = &PkcsKeyType;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = sizeof(PkcsKeyType);
#else
              PkcsTemplate[ii++].usValueLen = sizeof(PkcsKeyType);
#endif

              pCssmRsaPublic = (CSSM_RSA_PUBLIC_PTR) pCssmInKey->KeyData.Data;
              if (pCssmRsaPublic == NULL)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);
              
              if (pCssmRsaPublic->modulus.Data == NULL ||
                pCssmRsaPublic->modulus.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_MODULUS;
              PkcsTemplate[ii].pValue = pCssmRsaPublic->modulus.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmRsaPublic->modulus.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmRsaPublic->modulus.Length;
#endif

#if 0
              PkcsTemplate[ii].type = CKA_MODULUS_BITS;
              PkcsTemplate[ii].pValue = &pCssmRsaPublic->modulusBits;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = sizeof(pCssmRsaPublic->modulusBits);
#else
              PkcsTemplate[ii++].usValueLen = sizeof(pCssmRsaPublic->modulusBits);
#endif

#endif

              if (pCssmRsaPublic->publicExponent.Data == NULL ||
                pCssmRsaPublic->publicExponent.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_PUBLIC_EXPONENT;
              PkcsTemplate[ii].pValue = pCssmRsaPublic->publicExponent.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmRsaPublic->publicExponent.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmRsaPublic->publicExponent.Length;
#endif

              break;

            case CSSM_ALGID_DSA:
              PkcsKeyType = CKK_DSA;
              PkcsTemplate[ii].type = CKA_KEY_TYPE;
              PkcsTemplate[ii].pValue = &PkcsKeyType;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = sizeof(PkcsKeyType);
#else
              PkcsTemplate[ii++].usValueLen = sizeof(PkcsKeyType);
#endif

              pCssmDsaPublic = (CSSM_DSA_PUBLIC_PTR) pCssmInKey->KeyData.Data;
              if (pCssmDsaPublic == NULL)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);
              
              if (pCssmDsaPublic->prime.Data == NULL ||
                pCssmDsaPublic->prime.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_PRIME;
              PkcsTemplate[ii].pValue = pCssmDsaPublic->prime.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmDsaPublic->prime.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmDsaPublic->prime.Length;
#endif

              if (pCssmDsaPublic->subPrime.Data == NULL ||
                pCssmDsaPublic->subPrime.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_SUBPRIME;
              PkcsTemplate[ii].pValue = pCssmDsaPublic->subPrime.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmDsaPublic->subPrime.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmDsaPublic->subPrime.Length;
#endif

              if (pCssmDsaPublic->base.Data == NULL ||
                pCssmDsaPublic->base.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_BASE;
              PkcsTemplate[ii].pValue = pCssmDsaPublic->base.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmDsaPublic->base.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmDsaPublic->base.Length;
#endif

              if (pCssmDsaPublic->publicValue.Data == NULL ||
                pCssmDsaPublic->publicValue.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_VALUE;
              PkcsTemplate[ii].pValue = pCssmDsaPublic->publicValue.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmDsaPublic->publicValue.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmDsaPublic->publicValue.Length;
#endif
              break;

            case CSSM_ALGID_DH:
              PkcsKeyType = CKK_DH;
              PkcsTemplate[ii].type = CKA_KEY_TYPE;
              PkcsTemplate[ii].pValue = &PkcsKeyType;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = sizeof(PkcsKeyType);
#else
              PkcsTemplate[ii++].usValueLen = sizeof(PkcsKeyType);
#endif

              pCssmDhPublic = (CSSM_DH_PUBLIC_PTR) pCssmInKey->KeyData.Data;
              if (pCssmDhPublic == NULL)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);
              
              if (pCssmDhPublic->prime.Data == NULL ||
                pCssmDhPublic->prime.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_PRIME;
              PkcsTemplate[ii].pValue = pCssmDhPublic->prime.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmDhPublic->prime.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmDhPublic->prime.Length;
#endif

              if (pCssmDhPublic->base.Data == NULL ||
                pCssmDhPublic->base.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_BASE;
              PkcsTemplate[ii].pValue = pCssmDhPublic->base.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmDhPublic->base.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmDhPublic->base.Length;
#endif

              if (pCssmDhPublic->publicValue.Data == NULL ||
                pCssmDhPublic->publicValue.Length == 0)
                return SetErrNull(CSSM_CSP_INVALID_KEY_POINTER);

              PkcsTemplate[ii].type = CKA_VALUE;
              PkcsTemplate[ii].pValue = pCssmDhPublic->publicValue.Data;
#ifdef PKCS11_V20
              PkcsTemplate[ii++].ulValueLen = pCssmDhPublic->publicValue.Length;
#else
              PkcsTemplate[ii++].usValueLen = pCssmDhPublic->publicValue.Length;
#endif
              break;

              
#ifdef PKCS11_V20
            case CSSM_ALGID_ECDSA:
              PkcsKeyType = CKK_ECDSA;    
              break;

            case CSSM_ALGID_MAYFLY:
              PkcsKeyType = CKK_MAYFLY;
              break;
#endif

            default:
              return SetErrNull(CSSM_CSP_INVALID_ALGORITHM);
          
          }
        
        }
        else if (pCssmInHeader->KeyClass == CSSM_KEYCLASS_SESSION_KEY)
        {
          PkcsClass = CKO_SECRET_KEY;
          PkcsTemplate[ii].type = CKA_CLASS;
          PkcsTemplate[ii].pValue = &PkcsClass;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsClass);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsClass);
#endif

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_ENCRYPT))
            PkcsSessionEncrypt = TRUE;
          else
            PkcsSessionEncrypt = FALSE;
        
          PkcsTemplate[ii].type = CKA_ENCRYPT;
          PkcsTemplate[ii].pValue = &PkcsSessionEncrypt;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionEncrypt);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionEncrypt);
#endif

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_DECRYPT))
            PkcsSessionDecrypt = TRUE;
          else
            PkcsSessionDecrypt = FALSE;
        
          PkcsTemplate[ii].type = CKA_DECRYPT;
          PkcsTemplate[ii].pValue = &PkcsSessionDecrypt;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionDecrypt);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionDecrypt);
#endif

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_SIGN))
            PkcsSessionSign = TRUE;
          else
            PkcsSessionSign = FALSE;
        
          PkcsTemplate[ii].type = CKA_SIGN;
          PkcsTemplate[ii].pValue = &PkcsSessionSign;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionSign);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionSign);
#endif

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_VERIFY))
            PkcsSessionVerify = TRUE;
          else
            PkcsSessionVerify = FALSE;
        
          PkcsTemplate[ii].type = CKA_VERIFY;
          PkcsTemplate[ii].pValue = &PkcsSessionVerify;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionVerify);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionVerify);
#endif

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_WRAP))
            PkcsSessionWrap = TRUE;
          else
            PkcsSessionWrap = FALSE;
        
          PkcsTemplate[ii].type = CKA_WRAP;
          PkcsTemplate[ii].pValue = &PkcsSessionWrap;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionWrap);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionWrap);
#endif

          if ((pCssmInHeader->KeyUsage & CSSM_KEYUSE_ANY) ||
            (pCssmInHeader->KeyUsage & CSSM_KEYUSE_UNWRAP))
            PkcsSessionUnwrap = TRUE;
          else
            PkcsSessionUnwrap = FALSE;
        
          PkcsTemplate[ii].type = CKA_UNWRAP;
          PkcsTemplate[ii].pValue = &PkcsSessionUnwrap;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionUnwrap);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionUnwrap);
#endif

          if (pCssmInHeader->KeyAttr & CSSM_KEYATTR_SENSITIVE)
            PkcsSessionSensitive = TRUE;
          else
            PkcsSessionSensitive = FALSE;
        
          PkcsTemplate[ii].type = CKA_SENSITIVE;
          PkcsTemplate[ii].pValue = &PkcsSessionSensitive;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionSensitive);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionSensitive);
#endif      

          switch (pCssmInHeader->AlgorithmId)
          {
            case CSSM_ALGID_RC2:
              PkcsKeyType = CKK_RC2;
              bValueLenNeeded = CSSM_TRUE;
              break;

            case CSSM_ALGID_RC4:
              PkcsKeyType = CKK_RC4;
              bValueLenNeeded = CSSM_TRUE;
              break;

#ifdef PKCS11_V20
            case CSSM_ALGID_RC5:    
              PkcsKeyType = CKK_RC5;
              bValueLenNeeded = CSSM_TRUE;
              break;
#endif

            case CSSM_ALGID_DES:
              PkcsKeyType = CKK_DES;
              SetDesParity(&pCssmInKey->KeyData);
              break;

            case CSSM_ALGID_3DES_2KEY:
              PkcsKeyType = CKK_DES2;
              SetDesParity(&pCssmInKey->KeyData);
              break;

            case CSSM_ALGID_3DES_3KEY:
              PkcsKeyType = CKK_DES3;
              SetDesParity(&pCssmInKey->KeyData);
              break;

#ifdef PKCS11_V20           
            case CSSM_ALGID_CAST:   
              PkcsKeyType = CKK_CAST;
              break;

            case CSSM_ALGID_CAST3:
              PkcsKeyType = CKK_CAST3;
              break;

            case CSSM_ALGID_CAST5:
              PkcsKeyType = CKK_CAST5;
              break;

            case CSSM_ALGID_IDEA:
              PkcsKeyType = CKK_IDEA;
              break;

            case CSSM_ALGID_CDMF:
              PkcsKeyType = CKK_CDMF;
              break;

            case CSSM_ALGID_SKIPJACK:
              PkcsKeyType = CKK_SKIPJACK;
              break;

            case CSSM_ALGID_BATON:
              PkcsKeyType = CKK_BATON;
              break;

            case CSSM_ALGID_JUNIPER:
              PkcsKeyType = CKK_JUNIPER;
              break;

            case CSSM_ALGID_MD2_PBE:
              PkcsKeyType = CKK_DES;      
              break;
            
            case CSSM_ALGID_MD5_PBE:
              PkcsKeyType = CKK_DES;    
              break;
            
            case CSSM_ALGID_SSL3PreMasterGen:
              PkcsKeyType = CKK_GENERIC_SECRET;
              break;    
#endif

            default:
              return SetErrNull(CSSM_CSP_INVALID_ALGORITHM);
          
          }
          
          PkcsTemplate[ii].type = CKA_KEY_TYPE;
          PkcsTemplate[ii].pValue = &PkcsKeyType;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = sizeof(PkcsKeyType);
#else
          PkcsTemplate[ii++].usValueLen = sizeof(PkcsKeyType);
#endif

          PkcsTemplate[ii].type = CKA_VALUE;
          PkcsTemplate[ii].pValue = pCssmInKey->KeyData.Data;
#ifdef PKCS11_V20
          PkcsTemplate[ii++].ulValueLen = pCssmInKey->KeyData.Length;
#else
          PkcsTemplate[ii++].usValueLen = pCssmInKey->KeyData.Length;
#endif
        }


        if ((PkcsRc = C_CreateObject(pMsmSession->PkcsSessionHandle,
                       PkcsTemplate,
                       ii,
                       &hPkcsObject)) == CKR_OK)
        {
          if ((pCssmUniqueRecord = CssmMemFuncs.calloc_func(pMsmSession->CssmModuleHandle, 
                                    1, 
                                    sizeof(CSSM_DB_UNIQUE_RECORD))) == NULL)
          {
            return SetErrNull(CSSM_DL_MEMORY_ERROR);
          }
          
          if ((pCssmUniqueRecord->RecordIdentifier.Data = CssmMemFuncs.calloc_func(
                                      CssmDLDBHandle.DLHandle, 
                                      1, 
                                      sizeof(CK_OBJECT_HANDLE))) == NULL)
          {
            CssmMemFuncs.free_func(CssmDLDBHandle.DLHandle, pCssmUniqueRecord);
            return SetErrNull(CSSM_DL_MEMORY_ERROR);
          }

          *((CK_OBJECT_HANDLE_PTR) pCssmUniqueRecord->RecordIdentifier.Data) = hPkcsObject;
          pCssmUniqueRecord->RecordIdentifier.Length = sizeof(CK_OBJECT_HANDLE);
          
          return pCssmUniqueRecord;
        
        }
        else if (pCssmInHeader->KeyClass == CSSM_KEYCLASS_SESSION_KEY)
        {
          PkcsSavedRc = PkcsRc;
          
          
          if (bValueLenNeeded == CSSM_TRUE)
          {
            ii--;

            PkcsSessionValueLen = pCssmInKey->KeyData.Length;

            PkcsTemplate[ii].type = CKA_VALUE_LEN;
            PkcsTemplate[ii].pValue = &PkcsSessionValueLen;
#ifdef PKCS11_V20
            PkcsTemplate[ii++].ulValueLen = sizeof(PkcsSessionValueLen);
#else
            PkcsTemplate[ii++].usValueLen = sizeof(PkcsSessionValueLen);
#endif
          

            PkcsTemplate[ii].type = CKA_VALUE;
            PkcsTemplate[ii].pValue = pCssmInKey->KeyData.Data;
#ifdef PKCS11_V20
            PkcsTemplate[ii++].ulValueLen = pCssmInKey->KeyData.Length;
#else
            PkcsTemplate[ii++].usValueLen = pCssmInKey->KeyData.Length;
#endif
          }

          if ((PkcsRc = C_CreateFips140Object(pMsmSession->PkcsSessionHandle,
                    PkcsTemplate,
                    ii,
                    &hPkcsObject)) == CKR_OK)
          {
            if ((pCssmUniqueRecord = CssmMemFuncs.calloc_func(pMsmSession->CssmModuleHandle, 
                                    1, 
                                    sizeof(CSSM_DB_UNIQUE_RECORD))) == NULL)
            {
              return SetErrNull(CSSM_DL_MEMORY_ERROR);
            }

            if ((pCssmUniqueRecord->RecordIdentifier.Data = CssmMemFuncs.calloc_func(
                                      CssmDLDBHandle.DLHandle, 
                                      1, 
                                      sizeof(CK_OBJECT_HANDLE))) == NULL)
            {
              CssmMemFuncs.free_func(CssmDLDBHandle.DLHandle, pCssmUniqueRecord);
              return SetErrNull(CSSM_DL_MEMORY_ERROR);
            }

            *((CK_OBJECT_HANDLE_PTR) pCssmUniqueRecord->RecordIdentifier.Data) = hPkcsObject;
            pCssmUniqueRecord->RecordIdentifier.Length = sizeof(CK_OBJECT_HANDLE);
            
            return pCssmUniqueRecord;
          }
          else
          {
            return SetErrNull(PkcsSavedRc);
          }
        }
      }
      else
      {
        return SetErrNull(CSSM_DL_INVALID_PTR);
      }
    }
    else
    {
      return SetErrNull(CSSM_DL_INVALID_PTR);
    }
  }
  else
  {
    return SetErrNull(CSSM_DL_INVALID_DL_HANDLE);
  }
}



/*****************************************************************************
 * Function: DataDelete 
 *
 * Delete a record  
 *
 * Input:
 *  CssmDLDBHandle    - DL/DB handles 
 *  CssmRecordType    - Record type
 *  pCssmUniqueRecordId - Record identifier
 *
 * Output:
 *  None
 *
 * Returns:
 *  CSSM_OK       - Successful      
 *  CSSM_FAIL     - Failed
 *
 */

CSSM_RETURN CSSMAPI DataDelete (
    CSSM_DL_DB_HANDLE CssmDLDBHandle,
  CSSM_DB_RECORDTYPE CssmRecordType,
    const CSSM_DB_UNIQUE_RECORD_PTR pCssmUniqueRecord)
{
  MSMSESSION_PTR    pMsmSession;
  CK_RV       PkcsRc;

  if ((pMsmSession = FindMsmSession(CssmDLDBHandle.DLHandle)) != NULL)
  {
    if (CssmDLDBHandle.DBHandle != pMsmSession->CssmHandleInfo.SubServiceID)
      return SetErr(CSSM_DL_INVALID_DB_HANDLE);

    if (pCssmUniqueRecord == NULL || pCssmUniqueRecord->RecordIdentifier.Data == NULL)
      return SetErr(CSSM_DL_INVALID_PTR);

    if (CssmRecordType != CSSM_DL_DB_RECORD_PUBLIC_KEY &&
        CssmRecordType != CSSM_DL_DB_RECORD_PRIVATE_KEY &&
      CssmRecordType != CSSM_DL_DB_RECORD_SYMMETRIC_KEY &&
      CssmRecordType != CSSM_DL_DB_RECORD_CERT &&
      CssmRecordType != CSSM_DL_DB_RECORD_GENERIC)
        return SetErr(CSSM_DL_INVALID_RECORD_TYPE);

    if ((PkcsRc = C_DestroyObject(pMsmSession->PkcsSessionHandle,
                    *((CK_OBJECT_HANDLE*)(pCssmUniqueRecord->RecordIdentifier.Data)))) == CKR_OK)
      return CSSM_OK;
    else
      return SetErr(PkcsRc);
  }
  else
  {
    return SetErr(CSSM_DL_INVALID_DL_HANDLE);
  }
}



/*****************************************************************************
 * Function: C_CreateFips140Object 
 *
 * This function creates a session key object on a Fips40 token  
 *
 * Input:
 *  hSession      - PKCS11 session handle
 *  pTemplate     - Pointer to template of attributes of object to 
 *              be created
 *  uCount        - Number of attributes in template
 *
 * Output:
 *  phObject      - Location to receive new object handle
 *
 * Returns:
 *  CKR_OK        - Successful      
 *  CKR_XXX       - See PKCS11 Document
 *
 */

#ifdef PKCS11_V20
CK_RV CK_ENTRY C_CreateFips140Object(
  CK_SESSION_HANDLE hSession,
  CK_ATTRIBUTE_PTR pTemplate,
  CK_ULONG uCount,
  CK_OBJECT_HANDLE_PTR phObject)
#else
CK_RV CK_ENTRY C_CreateFips140Object(
  CK_SESSION_HANDLE hSession,
  CK_ATTRIBUTE_PTR pTemplate,
  CK_USHORT uCount,
  CK_OBJECT_HANDLE_PTR phObject)
#endif
{
  CK_RV       rc, rc1;
  CK_MECHANISM    mech;
  CK_OBJECT_HANDLE  hKey;
  CK_OBJECT_CLASS   keyClass  = CKO_SECRET_KEY;
  CK_KEY_TYPE     keyType = CKK_DES;
  CK_BBOOL      bToken = FALSE;
  CK_BBOOL            bSensitive = TRUE;
  CK_BBOOL      bPrivate = TRUE;
  CK_BBOOL      bEncrypt = TRUE;
  CK_BBOOL      bDecrypt = TRUE;
  CK_BBOOL      bWrap = TRUE;
  CK_BBOOL      bUnwrap = TRUE;

  CK_BYTE_PTR     pEncryptedData = NULL_PTR;
#ifdef PKCS11_V20
  CK_ULONG      encryptedDataLen;
#else
  CK_USHORT     encryptedDataLen;
#endif
   
   
  CK_ATTRIBUTE keyTemplate[] = {
    {CKA_CLASS, &keyClass, sizeof(keyClass)},
    {CKA_KEY_TYPE, &keyType, sizeof(keyType)},
    {CKA_TOKEN, &bToken, sizeof(bToken)},
    {CKA_SENSITIVE, &bSensitive, sizeof(bSensitive)},
    {CKA_PRIVATE, &bPrivate, sizeof(bPrivate)},
    {CKA_ENCRYPT, &bEncrypt, sizeof(bEncrypt)},
    {CKA_DECRYPT, &bDecrypt, sizeof(bDecrypt)},
    {CKA_WRAP, &bWrap, sizeof(bWrap)},
    {CKA_UNWRAP, &bUnwrap, sizeof(bUnwrap)}
  };
   

  mech.mechanism = CKM_DES_KEY_GEN;
  mech.pParameter = NULL_PTR;
#ifdef PKCS11_V20
  mech.ulParameterLen = 0;
#else
  mech.usParameterLen = 0;
#endif
   
    rc = C_GenerateKey(hSession,
                       &mech,
                       keyTemplate,
                       sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE),
                       &hKey);
  
  if (rc != CKR_OK)
    return rc;
    
  do {
    mech.mechanism = CKM_DES_ECB;
    rc = C_EncryptInit(hSession,
               &mech,
               hKey);

    if (rc != CKR_OK)
      break;

#ifdef PKCS11_V20
    encryptedDataLen = pTemplate[uCount-1].ulValueLen;
#else
    encryptedDataLen = pTemplate[uCount-1].usValueLen;
#endif

    if ((pEncryptedData = calloc(1, encryptedDataLen)) == NULL)
    {
      rc = CKR_HOST_MEMORY;
      break;
    }

    rc = C_Encrypt(hSession, 
             pTemplate[uCount-1].pValue,
             encryptedDataLen,
             pEncryptedData,
             &encryptedDataLen);
             
    if (rc != CKR_OK)
      break;

    rc = C_UnwrapKey(hSession, 
             &mech,
             hKey,
             pEncryptedData,
             encryptedDataLen,
             pTemplate,
             --uCount,
             phObject);
  } while (0);
  
  rc1 = C_DestroyObject(hSession, hKey);
  
  if (pEncryptedData != NULL)
    free(pEncryptedData);
 
  return rc;
}


