Files
mars-flaim/sql/src/f_nici.cpp
dsandersoremutah ffe3cb6975 Changed Id property
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@482 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-05-30 22:00:45 +00:00

2992 lines
64 KiB
C++

//------------------------------------------------------------------------------
// Desc: This file contains the functions needed for the NICI interface
// functions. Adapted from ss_crypto.c written by Cameron Mashayekhi.
//
// Tabs: 3
//
// Copyright (c) 2004-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id$
//------------------------------------------------------------------------------
#include "flaimsys.h"
#ifdef FLM_USE_NICI
FSTATIC void GetIV(
FLMBYTE * pucIV,
FLMUINT uiLen);
#endif
/*-----------------------------------------------------------------------------
* Desc: DTOR - Destroy an F_CCS object.
*---------------------------------------------------------------------------*/
F_CCS::~F_CCS()
{
#ifdef FLM_USE_NICI
if( m_keyHandle)
{
if( !m_hContext)
{
if( RC_BAD( CCS_CreateContext(0, &m_hContext)))
{
flmAssert( 0);
}
}
// Get rid of the key handle.
if ( m_hContext)
{
CCS_DestroyObject( m_hContext,
m_keyHandle);
CCS_DestroyContext( m_hContext);
}
}
if (m_hMutex != F_MUTEX_NULL)
{
f_mutexDestroy( &m_hMutex);
}
#endif
}
/*-----------------------------------------------------------------------------
* Desc: wrapNiciKey - Save the wrapped key in m_pKey. NOTE: Make sure
* there is a buffer allocated for the wrapped key (m_pucWrappedKey).
*---------------------------------------------------------------------------*/
RCODE F_CCS::wrapKey(
FLMBYTE ** ppucWrappedKey,
FLMUINT32 * pui32Length,
NICI_OBJECT_HANDLE masterWrappingKey)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( ppucWrappedKey);
F_UNREFERENCED_PARM( pui32Length);
F_UNREFERENCED_PARM( masterWrappingKey);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ATTRIBUTE wKey[2];
NICI_ALGORITHM algorithm;
NICI_PARAMETER_INFO parm[1];
FLMBYTE oid_aes128[] = {IDV_NOV_AES128CBCPad};
FLMBYTE oid_aes192[] = {IDV_NOV_AES192CBCPad};
FLMBYTE oid_aes256[] = {IDV_NOV_AES256CBCPad};
FLMBYTE oid_3des[] = {IDV_DES_EDE3_CBCPadIV8};
NICI_OBJECT_HANDLE wrappingKeyHandle;
FLMBOOL bLocked = FALSE;
if (masterWrappingKey)
{
wrappingKeyHandle = masterWrappingKey;
}
else
{
if (RC_BAD( rc = getWrappingKey( &wrappingKeyHandle)))
{
goto Exit;
}
}
f_mutexLock( m_hMutex);
bLocked = TRUE;
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
f_memset( &wKey, 0, sizeof(NICI_ATTRIBUTE) * 2);
wKey[0].type = NICI_A_KEY_TYPE;
wKey[1].type = NICI_A_KEY_SIZE;
if (RC_BAD( rc = CCS_GetAttributeValue(
m_hContext,
wrappingKeyHandle,
&wKey[0],
2)))
{
rc = RC_SET( NE_SFLM_NICI_ATTRIBUTE_VALUE);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (!wKey[0].u.f.hasValue || !wKey[1].u.f.hasValue)
{
rc = RC_SET( NE_SFLM_NICI_BAD_ATTRIBUTE);
goto Exit;
}
switch (wKey[0].u.f.value)
{
case NICI_K_AES:
{
switch (wKey[1].u.f.value)
{
case SFLM_AES128_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes128;
break;
}
case SFLM_AES192_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes192;
break;
}
case SFLM_AES256_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes256;
break;
}
default:
{
rc = RC_SET( NE_SFLM_INVALID_ENC_KEY_SIZE);
goto Exit;
}
}
algorithm.parameter = parm;
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
algorithm.parameter->parms[0].u.b.len = IV_SZ; /* 16-byte IV */
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)m_ucIV;
break;
}
case NICI_K_DES3X:
{
algorithm.algorithm = (nuint8 *)oid_3des;
algorithm.parameter = parm;
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
algorithm.parameter->parms[0].u.b.len = IV_SZ8; /* 8-byte IV */
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)m_ucIV;
break;
}
default:
{
rc = RC_SET( NE_SFLM_NICI_WRAPKEY_FAILED);
goto Exit;
}
}
// We should be able to call this with NULL for the wrapped key, to get the length.
if (RC_BAD( rc = CCS_WrapKey(
m_hContext,
&algorithm,
NICI_KM_UNSPECIFIED,
0,
wrappingKeyHandle,
m_keyHandle,
(nuint8 *)NULL,
(pnuint32)pui32Length)))
{
rc = RC_SET( NE_SFLM_NICI_WRAPKEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (RC_BAD( rc = f_calloc( *pui32Length, ppucWrappedKey)))
{
goto Exit;
}
if (RC_BAD( rc = CCS_WrapKey(
m_hContext,
&algorithm,
NICI_KM_UNSPECIFIED,
0,
wrappingKeyHandle,
m_keyHandle,
(nuint8 *)*ppucWrappedKey,
(pnuint32)pui32Length)))
{
rc = RC_SET( NE_SFLM_NICI_WRAPKEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
#endif
Exit:
#ifdef FLM_USE_NICI
if (bLocked)
{
f_mutexUnlock( m_hMutex);
}
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: - unwrapKey
*---------------------------------------------------------------------------*/
RCODE F_CCS::unwrapKey(
FLMBYTE * pucWrappedKey,
FLMUINT32 ui32WrappedKeyLength,
NICI_OBJECT_HANDLE masterWrappingKey)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucWrappedKey);
F_UNREFERENCED_PARM( ui32WrappedKeyLength);
F_UNREFERENCED_PARM( masterWrappingKey);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ATTRIBUTE wKey;
NICI_OBJECT_HANDLE wrappingKeyHandle;
FLMBOOL bLocked = FALSE;
if (masterWrappingKey)
{
wrappingKeyHandle = masterWrappingKey;
}
else
{
if (RC_BAD( rc = getWrappingKey( &wrappingKeyHandle)))
{
goto Exit;
}
}
f_mutexLock( m_hMutex);
bLocked = TRUE;
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
if (RC_BAD( rc = CCS_UnwrapKey(
m_hContext,
wrappingKeyHandle,
(nuint8 *)pucWrappedKey,
ui32WrappedKeyLength,
&m_keyHandle)))
{
rc = RC_SET( NE_SFLM_NICI_UNWRAPKEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// We need to get the key size...
f_memset( &wKey, 0, sizeof(NICI_ATTRIBUTE));
wKey.type = NICI_A_KEY_SIZE;
if (RC_BAD( rc = CCS_GetAttributeValue(
m_hContext,
m_keyHandle,
&wKey,
1)))
{
rc = RC_SET( NE_SFLM_NICI_ATTRIBUTE_VALUE);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (!wKey.u.f.hasValue)
{
rc = RC_SET( NE_SFLM_NICI_BAD_ATTRIBUTE);
goto Exit;
}
m_uiEncKeySize = wKey.u.f.value;
#endif
Exit:
#ifdef FLM_USE_NICI
if (bLocked)
{
f_mutexUnlock( m_hMutex);
}
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: generateEncryptionKey
*---------------------------------------------------------------------------*/
RCODE F_CCS::generateEncryptionKey(
FLMUINT uiEncKeySize
)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( uiEncKeySize);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
switch( m_eEncAlgorithm)
{
case SFLM_AES_ENCRYPTION:
{
rc = generateEncryptionKeyAES( uiEncKeySize);
break;
}
case SFLM_DES3_ENCRYPTION:
{
rc = generateEncryptionKeyDES3( uiEncKeySize);
break;
}
default:
{
flmAssert( 0);
rc = RC_SET( NE_SFLM_NICI_INVALID_ALGORITHM);
goto Exit;
}
}
#endif
Exit:
return rc;
}
/*-----------------------------------------------------------------------------
* Desc: generateEncryptionKey
*---------------------------------------------------------------------------*/
RCODE F_CCS::generateEncryptionKeyAES(
FLMUINT uiEncKeySize
)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( uiEncKeySize);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_ATTRIBUTE keyAttr[3];
nbool8 keySizeChanged;
FLMBYTE oid_aes128[] = {IDV_AES128CBC};
FLMBYTE oid_aes192[] = {IDV_AES192CBC};
FLMBYTE oid_aes256[] = {IDV_AES256CBC};
f_mutexLock( m_hMutex);
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
/* Set up AES Algorithm*/
switch (uiEncKeySize)
{
case SFLM_AES128_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes128;
break;
}
case SFLM_AES192_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes192;
break;
}
case SFLM_AES256_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes256;
break;
}
default:
{
rc = RC_SET( NE_SFLM_INVALID_ENC_KEY_SIZE);
goto Exit;
}
}
algorithm.parameterLen = 0;
algorithm.parameter = NULL;
/* Set up key attributes */
keyAttr[0].type = NICI_A_KEY_USAGE;
keyAttr[0].u.f.hasValue = 1;
keyAttr[0].u.f.value = NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT | NICI_F_EXTRACT;
keyAttr[0].u.f.valueInfo = 0;
keyAttr[1].type = NICI_A_KEY_SIZE;
keyAttr[1].u.f.hasValue = 1;
keyAttr[1].u.f.value = uiEncKeySize;
keyAttr[1].u.f.valueInfo = 0;
keyAttr[2].type = NICI_A_GLOBAL;
keyAttr[2].u.f.hasValue = 1;
keyAttr[2].u.f.value = N_TRUE;
keyAttr[2].u.f.valueInfo = 0;
/*Generate a AES key */
if (RC_BAD( rc = CCS_GenerateKey(
m_hContext,
&algorithm,
keyAttr,
3,
&keySizeChanged,
&m_keyHandle,
NICI_H_INVALID)))
{
rc = RC_SET( NE_SFLM_NICI_GENKEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Generate some IV to use with this key.
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)m_ucIV,
IV_SZ)))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
m_uiEncKeySize = uiEncKeySize;
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: generateEncryptionKey - DES3
*---------------------------------------------------------------------------*/
RCODE F_CCS::generateEncryptionKeyDES3(
FLMUINT uiEncKeySize
)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( uiEncKeySize);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_ATTRIBUTE keyAttr[3];
nbool8 keySizeChanged;
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
f_mutexLock( m_hMutex);
// Only one DES3 key size supported.
if (uiEncKeySize != SFLM_DES3_168_KEY_SIZE)
{
rc = RC_SET( NE_SFLM_INVALID_ENC_KEY_SIZE);
goto Exit;
}
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
/* Set up AES Algorithm*/
algorithm.algorithm = (nuint8 *)oid_des3;
algorithm.parameterLen = 0;
algorithm.parameter = NULL;
/* Set up key attributes */
keyAttr[0].type = NICI_A_KEY_USAGE;
keyAttr[0].u.f.hasValue = 1;
keyAttr[0].u.f.value = NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT | NICI_F_EXTRACT;
keyAttr[0].u.f.valueInfo = 0;
keyAttr[1].type = NICI_A_KEY_SIZE;
keyAttr[1].u.f.hasValue = 1;
keyAttr[1].u.f.value = uiEncKeySize;
keyAttr[1].u.f.valueInfo = 0;
keyAttr[2].type = NICI_A_GLOBAL;
keyAttr[2].u.f.hasValue = 1;
keyAttr[2].u.f.value = N_TRUE;
keyAttr[2].u.f.valueInfo = 0;
/*Generate a AES key */
if (RC_BAD( rc = CCS_GenerateKey(
m_hContext,
&algorithm,
keyAttr,
3,
&keySizeChanged,
&m_keyHandle,
NICI_H_INVALID)))
{
rc = RC_SET( NE_SFLM_NICI_GENKEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Generate some IV to use with this key.
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)m_ucIV,
IV_SZ)))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
m_uiEncKeySize = uiEncKeySize;
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: generateWrappingKey
*---------------------------------------------------------------------------*/
RCODE F_CCS::generateWrappingKey(
FLMUINT uiEncKeySize
)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( uiEncKeySize);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
switch( m_eEncAlgorithm)
{
case SFLM_AES_ENCRYPTION:
{
rc = generateWrappingKeyAES( uiEncKeySize);
break;
}
case SFLM_DES3_ENCRYPTION:
{
rc = generateWrappingKeyDES3( uiEncKeySize);
break;
}
default:
{
flmAssert( 0);
rc = RC_SET( NE_SFLM_NICI_INVALID_ALGORITHM);
goto Exit;
}
}
#endif
Exit:
return rc;
}
/*-----------------------------------------------------------------------------
* Desc: generateWrappingKeyAES - generates an AES wrapping key
*---------------------------------------------------------------------------*/
RCODE F_CCS::generateWrappingKeyAES(
FLMUINT uiEncKeySize)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( uiEncKeySize);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_ATTRIBUTE keyAttr[6];
nbool8 keySizeChanged;
FLMBYTE oid_aes128[] = {IDV_AES128CBC};
FLMBYTE oid_aes192[] = {IDV_AES192CBC};
FLMBYTE oid_aes256[] = {IDV_AES256CBC};
f_mutexLock( m_hMutex);
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
/* Set up AES Algorithm*/
switch (uiEncKeySize)
{
case SFLM_AES128_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes128;
keyAttr[1].u.v.valuePtr = oid_aes128;
keyAttr[1].u.v.valueLen = (nuint32)sizeof( oid_aes128);
break;
}
case SFLM_AES192_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes192;
keyAttr[1].u.v.valuePtr = oid_aes192;
keyAttr[1].u.v.valueLen = (nuint32)sizeof( oid_aes192);
break;
}
case SFLM_AES256_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes256;
keyAttr[1].u.v.valuePtr = oid_aes256;
keyAttr[1].u.v.valueLen = (nuint32)sizeof( oid_aes256);
break;
}
default:
{
rc = RC_SET( NE_SFLM_INVALID_ENC_KEY_SIZE);
goto Exit;
}
}
algorithm.parameterLen = 0;
algorithm.parameter = NULL;
/* Set up key attributes */
keyAttr[0].type = NICI_A_KEY_TYPE;
keyAttr[0].u.f.hasValue = 1;
keyAttr[0].u.f.value = NICI_K_AES;
keyAttr[0].u.f.valueInfo = 0;
keyAttr[1].type = NICI_A_KEY_FORMAT;
keyAttr[1].u.v.valueInfo = 0;
keyAttr[2].type = NICI_A_KEY_USAGE;
keyAttr[2].u.f.hasValue = 1;
keyAttr[2].u.f.value = NICI_F_WRAP | NICI_F_UNWRAP | NICI_F_KM_ENCRYPT | NICI_F_KM_DECRYPT | NICI_F_EXTRACT | NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT;
keyAttr[2].u.f.valueInfo = 0;
keyAttr[3].type = NICI_A_KEY_SIZE;
keyAttr[3].u.f.hasValue = 1;
keyAttr[3].u.f.value = uiEncKeySize;
keyAttr[3].u.f.valueInfo = 0;
keyAttr[4].type = NICI_A_GLOBAL;
keyAttr[4].u.f.hasValue = 1;
keyAttr[4].u.f.value = N_TRUE;
keyAttr[4].u.f.valueInfo = 0;
keyAttr[5].type = NICI_A_CLASS;
keyAttr[5].u.f.hasValue = 1;
keyAttr[5].u.f.value = NICI_O_SECRET_KEY;
keyAttr[5].u.f.valueInfo = 0;
/*Generate an AES wrapping key */
if (RC_BAD( rc = CCS_GenerateKey(
m_hContext,
&algorithm,
keyAttr,
6,
&keySizeChanged,
&m_keyHandle,
NICI_H_INVALID)))
{
rc = RC_SET( NE_SFLM_NICI_GENKEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Generate some IV to use with this key.
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)m_ucIV,
IV_SZ)))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// If we generated a wrapping key, then this object's key handle is actually a
// wrapping key. This means that we will use it to wrap the other keys in the
// system.
m_bKeyIsWrappingKey = TRUE;
m_uiEncKeySize = uiEncKeySize;
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: generateWrappingKeyDES3 - generates a triple DES (DES3) wrapping key
*---------------------------------------------------------------------------*/
RCODE F_CCS::generateWrappingKeyDES3(
FLMUINT uiEncKeySize)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( uiEncKeySize);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_ATTRIBUTE keyAttr[6];
nbool8 keySizeChanged;
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
f_mutexLock( m_hMutex);
if (uiEncKeySize != SFLM_DES3_168_KEY_SIZE)
{
rc = RC_SET( NE_SFLM_INVALID_ENC_KEY_SIZE);
goto Exit;
}
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
/* Set up AES Algorithm*/
algorithm.algorithm = (nuint8 *)oid_des3;
algorithm.parameterLen = 0;
algorithm.parameter = NULL;
/* Set up key attributes */
keyAttr[0].type = NICI_A_KEY_TYPE;
keyAttr[0].u.f.hasValue = 1;
keyAttr[0].u.f.value = NICI_K_DES3X;
keyAttr[0].u.f.valueInfo = 0;
keyAttr[1].type = NICI_A_KEY_FORMAT;
keyAttr[1].u.v.valuePtr = oid_des3;
keyAttr[1].u.v.valueLen = (nuint32)sizeof( oid_des3);
keyAttr[1].u.v.valueInfo = 0;
keyAttr[2].type = NICI_A_KEY_USAGE;
keyAttr[2].u.f.hasValue = 1;
keyAttr[2].u.f.value = NICI_F_WRAP | NICI_F_UNWRAP | NICI_F_KM_ENCRYPT | NICI_F_KM_DECRYPT | NICI_F_EXTRACT | NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT;
keyAttr[2].u.f.valueInfo = 0;
keyAttr[3].type = NICI_A_KEY_SIZE;
keyAttr[3].u.f.hasValue = 1;
keyAttr[3].u.f.value = uiEncKeySize;
keyAttr[3].u.f.valueInfo = 0;
keyAttr[4].type = NICI_A_GLOBAL;
keyAttr[4].u.f.hasValue = 1;
keyAttr[4].u.f.value = N_TRUE;
keyAttr[4].u.f.valueInfo = 0;
keyAttr[5].type = NICI_A_CLASS;
keyAttr[5].u.f.hasValue = 1;
keyAttr[5].u.f.value = NICI_O_SECRET_KEY;
keyAttr[5].u.f.valueInfo = 0;
/*Generate an AES wrapping key */
if (RC_BAD( rc = CCS_GenerateKey(
m_hContext,
&algorithm,
keyAttr,
6,
&keySizeChanged,
&m_keyHandle,
NICI_H_INVALID)))
{
rc = RC_SET( NE_SFLM_NICI_GENKEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Generate some IV to use with this key.
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)m_ucIV,
IV_SZ)))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// If we generated a wrapping key, then this object's key handle is actually a
// wrapping key. This means that we will use it to wrap the other keys in the
// system.
m_bKeyIsWrappingKey = TRUE;
m_uiEncKeySize = uiEncKeySize;
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: encryptToStore (public)
*---------------------------------------------------------------------------*/
RCODE F_CCS::encryptToStore(
FLMBYTE * pucIn,
FLMUINT uiInLen,
FLMBYTE * pucOut,
FLMUINT * puiOutLen,
FLMBYTE * pucIV)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucIn);
F_UNREFERENCED_PARM( uiInLen);
F_UNREFERENCED_PARM( pucOut);
F_UNREFERENCED_PARM( puiOutLen);
F_UNREFERENCED_PARM( pucIV);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
switch (m_eEncAlgorithm)
{
case SFLM_AES_ENCRYPTION:
{
rc = encryptToStoreAES(
pucIn,
uiInLen,
pucOut,
puiOutLen,
pucIV);
break;
}
case SFLM_DES3_ENCRYPTION:
{
rc = encryptToStoreDES3(
pucIn,
uiInLen,
pucOut,
puiOutLen,
pucIV);
break;
}
default:
{
flmAssert( 0);
rc = RC_SET( NE_SFLM_NICI_INVALID_ALGORITHM);
goto Exit;
}
}
#endif
Exit:
return rc;
}
/*-----------------------------------------------------------------------------
* Desc: decryptFromStore (public)
*---------------------------------------------------------------------------*/
RCODE F_CCS::decryptFromStore(
FLMBYTE * pucIn,
FLMUINT uiInLen,
FLMBYTE * pucOut,
FLMUINT * puiOutLen,
FLMBYTE * pucIV)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucIn);
F_UNREFERENCED_PARM( uiInLen);
F_UNREFERENCED_PARM( pucOut);
F_UNREFERENCED_PARM( puiOutLen);
F_UNREFERENCED_PARM( pucIV);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
switch( m_eEncAlgorithm)
{
case SFLM_AES_ENCRYPTION:
{
rc = decryptFromStoreAES(
pucIn,
uiInLen,
pucOut,
puiOutLen,
pucIV);
break;
}
case SFLM_DES3_ENCRYPTION:
{
rc = decryptFromStoreDES3(
pucIn,
uiInLen,
pucOut,
puiOutLen,
pucIV);
break;
}
default:
{
flmAssert( 0);
rc = RC_SET( NE_SFLM_NICI_INVALID_ALGORITHM);
goto Exit;
}
}
#endif
Exit:
return rc;
}
/*-----------------------------------------------------------------------------
* Desc: encryptToStore - Using AES
*---------------------------------------------------------------------------*/
RCODE F_CCS::encryptToStoreAES(
FLMBYTE * pucIn,
FLMUINT uiInLen,
FLMBYTE * pucOut,
FLMUINT * puiOutLen,
FLMBYTE * pucIV)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucIn);
F_UNREFERENCED_PARM( uiInLen);
F_UNREFERENCED_PARM( pucOut);
F_UNREFERENCED_PARM( puiOutLen);
F_UNREFERENCED_PARM( pucIV);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_PARAMETER_INFO parm[1];
FLMBYTE oid_aes128[] = {IDV_AES128CBC};
FLMBYTE oid_aes192[] = {IDV_AES192CBC};
FLMBYTE oid_aes256[] = {IDV_AES256CBC};
f_mutexLock( m_hMutex);
/* Create NICI Context*/
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
switch (m_uiEncKeySize)
{
case SFLM_AES128_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes128;
break;
}
case SFLM_AES192_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes192;
break;
}
case SFLM_AES256_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes256;
break;
}
default:
{
rc = RC_SET( NE_SFLM_INVALID_ENC_KEY_SIZE);
goto Exit;
}
}
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter = parm;
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
if (pucIV)
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)pucIV;
}
else
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)m_ucIV;
}
algorithm.parameter->parms[0].u.b.len = IV_SZ;
/* init encryption */
if (RC_BAD( rc = CCS_DataEncryptInit( m_hContext, &algorithm, m_keyHandle)))
{
rc = RC_SET_AND_ASSERT( NE_SFLM_NICI_ENC_INIT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (RC_BAD( rc = CCS_Encrypt(
m_hContext,
(nuint8 *)pucIn,
uiInLen,
(nuint8 *)pucOut,
puiOutLen)))
{
rc = RC_SET( NE_SFLM_NICI_ENCRYPT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: decryptFromStore - using the AES algorithm
*---------------------------------------------------------------------------*/
RCODE F_CCS::decryptFromStoreAES(
FLMBYTE * pucIn,
FLMUINT uiInLen,
FLMBYTE * pucOut,
FLMUINT * puiOutLen,
FLMBYTE * pucIV)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucIn);
F_UNREFERENCED_PARM( uiInLen);
F_UNREFERENCED_PARM( pucOut);
F_UNREFERENCED_PARM( puiOutLen);
F_UNREFERENCED_PARM( pucIV);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_PARAMETER_INFO parm[1];
FLMBYTE oid_aes128[] = {IDV_AES128CBC};
FLMBYTE oid_aes192[] = {IDV_AES192CBC};
FLMBYTE oid_aes256[] = {IDV_AES256CBC};
f_mutexLock( m_hMutex);
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
switch (m_uiEncKeySize)
{
case SFLM_AES128_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes128;
break;
}
case SFLM_AES192_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes192;
break;
}
case SFLM_AES256_KEY_SIZE:
{
algorithm.algorithm = (nuint8 *)oid_aes256;
break;
}
default:
{
rc = RC_SET( NE_SFLM_INVALID_ENC_KEY_SIZE);
goto Exit;
}
}
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter = parm;
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
if (pucIV)
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)pucIV;
}
else
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)m_ucIV;
}
algorithm.parameter->parms[0].u.b.len = IV_SZ; /* 16-byte IV */
/* init encryption */
if (RC_BAD( rc = CCS_DataDecryptInit(
m_hContext,
&algorithm,
m_keyHandle)))
{
rc = RC_SET( NE_SFLM_NICI_DECRYPT_INIT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (RC_BAD( rc = CCS_Decrypt(
m_hContext,
(nuint8 *)pucIn,
uiInLen,
(nuint8 *)pucOut,
puiOutLen)))
{
rc = RC_SET( NE_SFLM_NICI_DECRYPT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: encryptToStore - Using DES3
*---------------------------------------------------------------------------*/
RCODE F_CCS::encryptToStoreDES3(
FLMBYTE * pucIn,
FLMUINT uiInLen,
FLMBYTE * pucOut,
FLMUINT * puiOutLen,
FLMBYTE * pucIV)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucIn);
F_UNREFERENCED_PARM( uiInLen);
F_UNREFERENCED_PARM( pucOut);
F_UNREFERENCED_PARM( puiOutLen);
F_UNREFERENCED_PARM( pucIV);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_PARAMETER_INFO parm[1];
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
f_mutexLock( m_hMutex);
/* Create NICI Context*/
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
algorithm.algorithm = (nuint8 *)oid_des3;
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter = parm;
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
if (pucIV)
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)pucIV;
}
else
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)m_ucIV;
}
algorithm.parameter->parms[0].u.b.len = IV_SZ8; /* 8-byte IV */
/* init encryption */
if (RC_BAD( rc = CCS_DataEncryptInit(m_hContext, &algorithm, m_keyHandle)))
{
rc = RC_SET_AND_ASSERT( NE_SFLM_NICI_ENC_INIT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (RC_BAD( rc = CCS_Encrypt(
m_hContext,
(nuint8 *)pucIn,
uiInLen,
(nuint8 *)pucOut,
puiOutLen)))
{
rc = RC_SET( NE_SFLM_NICI_ENCRYPT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: decryptFromStore - using the Triple DES (DES3) algorithm
*---------------------------------------------------------------------------*/
RCODE F_CCS::decryptFromStoreDES3(
FLMBYTE * pucIn,
FLMUINT uiInLen,
FLMBYTE * pucOut,
FLMUINT * puiOutLen,
FLMBYTE * pucIV)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucIn);
F_UNREFERENCED_PARM( uiInLen);
F_UNREFERENCED_PARM( pucOut);
F_UNREFERENCED_PARM( puiOutLen);
F_UNREFERENCED_PARM( pucIV);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_PARAMETER_INFO parm[1];
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
f_mutexLock( m_hMutex);
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
/*Set up alogrithm now to do triple des decryption */
algorithm.algorithm = (nuint8 *)oid_des3;
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter = parm;
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
if (pucIV)
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)pucIV;
}
else
{
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)m_ucIV;
}
algorithm.parameter->parms[0].u.b.len = IV_SZ8; /* 8-byte IV */
/* init encryption */
if (RC_BAD( rc = CCS_DataDecryptInit(
m_hContext,
&algorithm,
m_keyHandle)))
{
rc = RC_SET( NE_SFLM_NICI_DECRYPT_INIT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (RC_BAD( rc = CCS_Decrypt(
m_hContext,
(nuint8 *)pucIn,
uiInLen,
(nuint8 *)pucOut,
puiOutLen)))
{
rc = RC_SET( NE_SFLM_NICI_DECRYPT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: init - Initialize the context.
*---------------------------------------------------------------------------*/
RCODE F_CCS::init(
FLMBOOL bKeyIsWrappingKey,
eEncAlgorithm eEncAlg)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( bKeyIsWrappingKey);
F_UNREFERENCED_PARM( eEncAlg);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
FLMBOOL bLocked = FALSE;
if (m_bInitCalled)
{
rc = RC_SET_AND_ASSERT( NE_SFLM_ILLEGAL_OP);
goto Exit;
}
m_bKeyIsWrappingKey = bKeyIsWrappingKey;
if (eEncAlg != SFLM_AES_ENCRYPTION &&
eEncAlg != SFLM_DES3_ENCRYPTION)
{
flmAssert( 0);
rc = RC_SET( NE_SFLM_INVALID_ENC_ALGORITHM);
goto Exit;
}
m_eEncAlgorithm = eEncAlg;
// Create a mutex to control access to the nici operations.
if (RC_BAD( rc = f_mutexCreate( &m_hMutex)))
{
goto Exit;
}
f_mutexLock( m_hMutex);
bLocked = TRUE;
// Create NICI Context
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
else
{
flmAssert( 0); // Should not have a context yet!
}
// Generate the Random IV
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)&m_ucRndIV,
IV_SZ)))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Generate an adjustment factor for the IV
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)&m_uiIVFactor,
sizeof(FLMUINT))))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
m_bInitCalled = TRUE;
#endif
Exit:
#ifdef FLM_USE_NICI
if (bLocked)
{
f_mutexUnlock( m_hMutex);
}
#endif
return rc;
}
/*-----------------------------------------------------------------------------
* Desc: selectWrappingKey - pick a wrapping key that we can use to wrap &
* unwrap the encryption key with.
*---------------------------------------------------------------------------*/
RCODE F_CCS::getWrappingKey(
NICI_OBJECT_HANDLE * pWrappingKeyHandle)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pWrappingKeyHandle);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ATTRIBUTE find[2];
FLMUINT uiCount;
f_mutexLock( m_hMutex);
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
find[0].type = NICI_A_GLOBAL;
find[0].u.f.hasValue = 1;
find[0].u.f.value = 1;
find[0].u.f.valueInfo = 0;
find[1].type = NICI_A_FEATURE;
find[1].u.f.hasValue = 1;
find[1].u.f.value = NICI_AV_STORAGE;
find[1].u.f.valueInfo = 0;
if (RC_BAD( rc = CCS_FindObjectsInit(m_hContext, find, 2)))
{
rc = RC_SET( NE_SFLM_NICI_FIND_INIT);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
uiCount = 1;
if (RC_BAD( rc = CCS_FindObjects(
m_hContext,
pWrappingKeyHandle,
&uiCount)))
{
rc = RC_SET( NE_SFLM_NICI_FIND_OBJECT);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (uiCount < 1)
{
rc = RC_SET( NE_SFLM_NICI_WRAPKEY_NOT_FOUND);
goto Exit;
}
#endif
Exit:
#ifdef FLM_USE_NICI
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: getKeyToStore - Function used to obtain the key information in the
* format that will be stored on disk. A buffer will be allocated by this
* function that **MUST** be freed when no longer needed.
*---------------------------------------------------------------------------*/
RCODE F_CCS::getKeyToStore(
FLMBYTE ** ppucKeyInfo,
FLMUINT32 * pui32BufLen,
FLMBYTE * pszEncKeyPasswd,
F_CCS * pWrappingCcs)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( ppucKeyInfo);
F_UNREFERENCED_PARM( pui32BufLen);
F_UNREFERENCED_PARM( pszEncKeyPasswd);
F_UNREFERENCED_PARM( pWrappingCcs);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
FLMBYTE * pucTmp = NULL;
FLMBYTE * pucPtr = NULL;
FLMUINT32 ui32PaddedLength;
FLMBYTE * pucWrappedKey = NULL;
FLMUINT32 ui32WrappedKeyLen = 0;
FLMBYTE * pszFormattedEncKeyPasswd = NULL;
NICI_OBJECT_HANDLE wrappingKeyHandle = 0;
*ppucKeyInfo = NULL;
*pui32BufLen = 0;
if (pWrappingCcs)
{
flmAssert(m_bKeyIsWrappingKey == FALSE);
wrappingKeyHandle = pWrappingCcs->m_keyHandle;
}
else if (!pszEncKeyPasswd)
{
flmAssert( m_bKeyIsWrappingKey);
}
// Either extract the key or wrap the key.
if (pszEncKeyPasswd && pszEncKeyPasswd[0])
{
// The password that is passed in to CCS_pbeEncrypt is NOT actually
// unicode. It must be treated as a sequence of bytes that that is
// terminated with 2 nulls and has an even length. If we treat it
// as unicode, then we'll have endian issues if we move the database
// to machines with different byte ordering.
if (RC_BAD( rc = f_calloc( f_strlen(pszEncKeyPasswd) +
(f_strlen(pszEncKeyPasswd) % 2) + 2,
&pszFormattedEncKeyPasswd)))
{
goto Exit;
}
f_strcpy( pszFormattedEncKeyPasswd, pszEncKeyPasswd);
if (RC_BAD( rc = extractKey( &pucWrappedKey,
&ui32WrappedKeyLen,
(FLMUNICODE *)pszFormattedEncKeyPasswd)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = wrapKey( &pucWrappedKey,
&ui32WrappedKeyLen,
wrappingKeyHandle)))
{
goto Exit;
}
}
// The shrouded or wrapped key will be stored in m_pKey.
ui32PaddedLength = (ui32WrappedKeyLen +
sizeof( FLMBOOL) +
sizeof (FLMUINT32) +
IV_SZ );
// Make sure our buffer size is padded to a 16 byte boundary.
if ((ui32PaddedLength % 16) != 0)
{
ui32PaddedLength += (16 - (ui32PaddedLength % 16));
}
// Add one extra byte for a NULL terminator
if (RC_BAD(rc = f_alloc( ui32PaddedLength + 1, &pucTmp)))
{
goto Exit;
}
if ( !m_hContext)
{
if (CCS_CreateContext( 0, &m_hContext))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
pucPtr = pucTmp;
// Save a flag indicating whether the key is wrapped or encoded in
// a password.
UD2FBA( (pszEncKeyPasswd && pszEncKeyPasswd[0]) ? (FLMUINT)TRUE : (FLMUINT)FALSE, pucPtr);
pucPtr += sizeof(FLMBOOL);
// Copy the key length.
UD2FBA(ui32WrappedKeyLen, pucPtr);
pucPtr += sizeof(FLMUINT32);
// Copy the IV too.
f_memcpy( pucPtr, m_ucIV, IV_SZ);
pucPtr += IV_SZ;
// Copy the wrapped key value
f_memcpy( pucPtr, pucWrappedKey, ui32WrappedKeyLen);
pucPtr += ui32WrappedKeyLen;
// Fill the remainder of the buffer with random data.
if (CCS_GetRandom(m_hContext,
(nuint8 *)pucPtr,
((FLMUINT)pucTmp + ui32PaddedLength) - (FLMUINT)pucPtr))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
pucTmp[ ui32PaddedLength] = '\0';
*ppucKeyInfo = pucTmp;
*pui32BufLen = ui32PaddedLength;
pucTmp = NULL;
#endif
Exit:
#ifdef FLM_USE_NICI
if (pucTmp)
{
f_free(&pucTmp);
}
if (pucWrappedKey)
{
f_free( &pucWrappedKey);
}
if (pszFormattedEncKeyPasswd)
{
f_free( &pszFormattedEncKeyPasswd);
}
#endif
return rc;
}
/*-----------------------------------------------------------------------------
* Desc: setKeyFromStore - Function used to set the key info using the binary
* key stored on the disk.
*---------------------------------------------------------------------------*/
RCODE F_CCS::setKeyFromStore(
FLMBYTE * pucKeyInfo,
FLMBYTE * pszEncKeyPasswd,
F_CCS * pWrappingCcs)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucKeyInfo);
F_UNREFERENCED_PARM( pszEncKeyPasswd);
F_UNREFERENCED_PARM( pWrappingCcs);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
FLMBYTE * pucTmp = pucKeyInfo;
FLMBYTE * pucBuffer = NULL;
FLMBOOL bShrouded = FALSE;
FLMUINT32 ui32Length;
FLMBYTE * pucKeyBuf = NULL;
FLMBYTE * pszFormattedEncKeyPasswd = NULL;
NICI_OBJECT_HANDLE wrappingKeyHandle = 0;
if (pWrappingCcs)
{
flmAssert(m_bKeyIsWrappingKey == FALSE);
wrappingKeyHandle = pWrappingCcs->m_keyHandle;
}
// Extract the fields from the buffer
// Is the key shrouded?
bShrouded = FB2UD( pucTmp);
pucTmp += sizeof(FLMUINT);
// Actual length - note that the passed buffer is padded to 16 byte boundary.
ui32Length = FB2UD( pucTmp);
pucTmp += sizeof(FLMUINT32);
// Get the IV
f_memcpy( m_ucIV, pucTmp, IV_SZ);
pucTmp += IV_SZ;
// Need another temporary buffer to hold the encrypted / shrouded key.
if (RC_BAD( rc = f_alloc( ui32Length, &pucBuffer)))
{
goto Exit;
}
f_memcpy( pucBuffer, pucTmp, ui32Length);
if (bShrouded)
{
if (pszEncKeyPasswd == NULL || pszEncKeyPasswd[0] == '\0')
{
rc = RC_SET( NE_SFLM_EXPECTING_PASSWORD);
goto Exit;
}
// The password that is passed in to CCS_pbeDecrypt is NOT actually
// unicode. It must be treated as a sequence of bytes that that is
// terminated with 2 nulls and has an even length. If we treat it
// as unicode, then we'll have endian issues if we move the database
// to machines with different byte ordering.
if (RC_BAD( rc = f_calloc( f_strlen(pszEncKeyPasswd) +
(f_strlen(pszEncKeyPasswd) % 2) + 2,
&pszFormattedEncKeyPasswd)))
{
goto Exit;
}
f_strcpy( pszFormattedEncKeyPasswd, pszEncKeyPasswd);
// Unshroud the key using the password.
// Key handle is always kept in m_keyHandle.
if (RC_BAD( rc = injectKey( pucBuffer,
ui32Length,
(FLMUNICODE *)pszFormattedEncKeyPasswd)))
{
goto Exit;
}
}
else
{
if (pszEncKeyPasswd)
{
if ( pszEncKeyPasswd[0] != '\0')
{
rc = RC_SET( NE_SFLM_NOT_EXPECTING_PASSWORD);
goto Exit;
}
}
// Unwrap the key. The Key handle is always store in m_keyHandle.
if (RC_BAD( rc = unwrapKey( pucBuffer,
ui32Length,
wrappingKeyHandle)))
{
goto Exit;
}
}
m_bKeyVerified = TRUE;
#endif
Exit:
#ifdef FLM_USE_NICI
if (pucBuffer)
{
f_free( &pucBuffer);
}
if (pucKeyBuf)
{
f_free( &pucKeyBuf);
}
if (pszFormattedEncKeyPasswd)
{
f_free( &pszFormattedEncKeyPasswd);
}
#endif
return rc;
}
typedef struct
{
FLMUINT uiKeyType;
FLMUINT uiFormatLen;
FLMUINT uiKeyLen;
FLMUINT uiKeySize;
} EXTRACTED_KEY;
/*-----------------------------------------------------------------------------
* Desc: extractKey - Extract the key by encrypting it in a supplied password. The
* buffer ppucExtractedKey buffer is allocated and returned, thus *MUST* be released
* after it is no longer needed.
*---------------------------------------------------------------------------*/
RCODE F_CCS::extractKey(
FLMBYTE ** ppucExtractedKey,
FLMUINT32 * pui32Length,
FLMUNICODE * puzEncKeyPasswd)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( ppucExtractedKey);
F_UNREFERENCED_PARM( pui32Length);
F_UNREFERENCED_PARM( puzEncKeyPasswd);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_ATTRIBUTE keyAttr[2];
NICI_ATTRIBUTE attr[2];
FLMBYTE oid_sha1[] = {IDV_SHA1};
FLMBYTE oid_pbe[] = {IDV_pbeWithSHA1And3Key3xDES_CBC};
FLMBYTE ucDigest[ 20];
FLMUINT uiDigestLen = sizeof(ucDigest);
FLMUINT uiBufferSize;
FLMBYTE * pucKey = NULL;
FLMBYTE * pucFormat = NULL;
EXTRACTED_KEY * pExtractedKey = NULL;
FLMUINT uiEncLen;
FLMBYTE * pTemp = NULL;
NICI_PARAMETER_INFO * pParmInfo;
FLMBYTE * pucSalt;
FLMUINT uiAllocSize;
FLMUINT uiIndx;
FLMBYTE * pucTempPtr;
f_mutexLock( m_hMutex);
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
f_memset( &attr[0], 0, sizeof(NICI_ATTRIBUTE) * 2);
attr[0].type = NICI_A_KEY_TYPE;
attr[1].type = NICI_A_KEY_FORMAT;
if (RC_BAD( rc = CCS_GetAttributeValue(
m_hContext,
m_keyHandle,
&attr[0],
2)))
{
rc = RC_SET( NE_SFLM_NICI_ATTRIBUTE_VALUE);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (!attr[0].u.f.hasValue)
{
rc = RC_SET( NE_SFLM_NICI_BAD_ATTRIBUTE);
goto Exit;
}
f_memset( &keyAttr[0], 0, sizeof(NICI_ATTRIBUTE) * 2);
switch (attr[0].u.f.value)
{
case NICI_K_AES:
{
uiIndx = 0;
keyAttr[uiIndx].type = NICI_A_KEY_VALUE;
switch (m_uiEncKeySize)
{
case SFLM_AES128_KEY_SIZE:
{
keyAttr[uiIndx].u.v.valueLen = 16;
break;
}
case SFLM_AES192_KEY_SIZE:
{
keyAttr[uiIndx].u.v.valueLen = 24;
break;
}
case SFLM_AES256_KEY_SIZE:
{
keyAttr[uiIndx].u.v.valueLen = 32;
break;
}
}
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_FORMAT;
keyAttr[uiIndx].u.v.valueLen = attr[1].u.v.valueLen;
break;
}
case NICI_K_DES3X:
{
uiIndx = 0;
keyAttr[uiIndx].type = NICI_A_KEY_VALUE;
keyAttr[uiIndx].u.v.valueLen = 24;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_FORMAT;
keyAttr[uiIndx].u.v.valueLen = attr[1].u.v.valueLen;
break;
}
case NICI_K_DES:
{
uiIndx = 0;
keyAttr[uiIndx].type = NICI_A_KEY_VALUE;
keyAttr[uiIndx].u.v.valueLen = 8;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_FORMAT;
keyAttr[uiIndx].u.v.valueLen = attr[1].u.v.valueLen;
break;
}
default:
{
flmAssert( 0);
rc = RC_SET( NE_SFLM_NICI_INVALID_ALGORITHM);
goto Exit;
}
}
// Make one allocation that we can then use to hold several different things.
uiBufferSize = sizeof( EXTRACTED_KEY) + // pExtractedKey
attr[1].u.v.valueLen + // pucFormat
keyAttr[0].u.v.valueLen + // pucKey
sizeof (ucDigest); // pucDigest
uiAllocSize = uiBufferSize +
SALT_SZ + // Salt (not encrypted)
(sizeof(NICI_PARAMETER_DATA) * 2) + sizeof(FLMUINT32); // Parameter data (not encrypted)
// Make sure the allocation size is on a 8 byte boundary
if( (uiAllocSize % 8) != 0)
{
uiAllocSize += (8 - (uiAllocSize % 8));
}
if (RC_BAD( rc = f_calloc( uiAllocSize, &pExtractedKey)))
{
goto Exit;
}
keyAttr[1].u.v.valuePtr = &pExtractedKey[1];
pucFormat = (FLMBYTE *)keyAttr[1].u.v.valuePtr;
keyAttr[0].u.v.valuePtr = pucFormat + attr[1].u.v.valueLen;
pucKey = (FLMBYTE *)keyAttr[0].u.v.valuePtr;
pucSalt = (FLMBYTE *)pExtractedKey + uiBufferSize;
pParmInfo = (NICI_PARAMETER_INFO *)(pucSalt + SALT_SZ);
// Make sure that pParmInfo is 8 byte alligned.
if ((FLMUINT)pParmInfo % 8)
{
FLMBYTE * pucTemp = (FLMBYTE *)pParmInfo +
(8 - ((FLMUINT)pParmInfo % 8));
pParmInfo = (NICI_PARAMETER_INFO *)pucTemp;
}
// Extracted the key value now
if (RC_BAD( rc = CCS_ExtractKey(
m_hContext,
m_keyHandle,
&keyAttr[0],
2)))
{
rc = RC_SET( NE_SFLM_EXTRACT_KEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Calculate a SHA1 checksum.
algorithm.algorithm = (nuint8 *)oid_sha1;
algorithm.parameter = NULL;
algorithm.parameterLen = 0;
if (RC_BAD( rc = CCS_DigestInit(
m_hContext,
&algorithm)))
{
rc = RC_SET( NE_SFLM_DIGEST_INIT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (RC_BAD( rc = CCS_Digest(
m_hContext,
(nuint8 *)pucFormat,
keyAttr[0].u.v.valueLen + attr[1].u.v.valueLen,
(nuint8 *)ucDigest,
&uiDigestLen)))
{
rc = RC_SET( NE_SFLM_DIGEST_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
flmAssert( uiDigestLen == sizeof( ucDigest));
pucTempPtr = (FLMBYTE *)pExtractedKey;
UD2FBA( attr[0].u.f.value, pucTempPtr); //pExtractedKey->uiKeyType = attr[0].u.f.value;
pucTempPtr += 4;
UD2FBA( attr[1].u.v.valueLen, pucTempPtr); //pExtractedKey->uiFormatLen = attr[1].u.v.valueLen;
pucTempPtr += 4;
UD2FBA( keyAttr[0].u.v.valueLen, pucTempPtr); //pExtractedKey->uiKeyLen = keyAttr[0].u.v.valueLen;
pucTempPtr += 4;
UD2FBA( m_uiEncKeySize, pucTempPtr); // pEncKey->uiKeySize = m_uiEncKeySize;
// Point to the Digest...
pTemp = (FLMBYTE *)&pExtractedKey[1] +
attr[1].u.v.valueLen + // Format length
keyAttr[0].u.v.valueLen; // Key length
f_memcpy( pTemp, ucDigest, uiDigestLen);
// Generate some salt.
if (RC_BAD( rc = CCS_GetRandom( m_hContext,
(nuint8 *)pucSalt,
SALT_SZ)))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
pTemp = NULL; // don't want this to be freed
goto Exit;
}
// This buffer needs to be a separate allocation because it is returned to the caller. We will
// be returning the value of the SALT with the encrypted key. The call to CCS_pbeEncrypt
// may return an extra 8 bytes.
if (RC_BAD( rc = f_alloc( uiBufferSize + SALT_SZ + 8, &pTemp)))
{
goto Exit;
}
// Now to encrypt the buffer.
algorithm.algorithm = (nuint8 *)oid_pbe;
pParmInfo->count = 2; // Two parameters
pParmInfo->parms[0].parmType = NICI_P_SALT;
pParmInfo->parms[0].u.b.len = SALT_SZ;
pParmInfo->parms[0].u.b.ptr = (nuint8 *)pucSalt;
pParmInfo->parms[1].parmType = NICI_P_COUNT;
pParmInfo->parms[1].u.value = SALT_COUNT;
algorithm.parameter = pParmInfo;
algorithm.parameterLen = sizeof(NICI_PARAMETER_DATA) * 2 + sizeof(FLMUINT32);
uiEncLen = uiBufferSize + 8;
if (RC_BAD( rc = CCS_pbeEncrypt(
m_hContext,
&algorithm,
puzEncKeyPasswd,
(nuint8 *)pExtractedKey,
uiBufferSize,
(nuint8 *)pTemp,
&uiEncLen)))
{
rc = RC_SET( NE_SFLM_PBE_ENCRYPT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
*ppucExtractedKey = pTemp;
// Now add the salt to the end of the buffer.
pTemp += uiEncLen;
f_memcpy( pTemp, pucSalt, SALT_SZ);
pTemp = NULL;
*pui32Length = uiEncLen + SALT_SZ;
#endif
Exit:
#ifdef FLM_USE_NICI
if (pTemp)
{
f_free( &pTemp);
}
if (pucKey)
{
f_free( &pExtractedKey);
}
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/*-----------------------------------------------------------------------------
* Desc: injectKey - Inject the encrypting key using the supplied password.
*---------------------------------------------------------------------------*/
RCODE F_CCS::injectKey(
FLMBYTE * pszExtractedKey,
FLMUINT32 ui32Length,
FLMUNICODE * puzEncKeyPasswd)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pszExtractedKey);
F_UNREFERENCED_PARM( ui32Length);
F_UNREFERENCED_PARM( puzEncKeyPasswd);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_ALGORITHM algorithm;
NICI_ATTRIBUTE keyAttr[7];
FLMBYTE oid_sha1[] = {IDV_SHA1};
FLMBYTE oid_pbe[] = {IDV_pbeWithSHA1And3Key3xDES_CBC};
FLMUINT uiIndx;
FLMBYTE ucDigest[ 20];
FLMUINT uiDigestLen = sizeof(ucDigest);
FLMBYTE * pKey;
FLMBYTE * pucFormat;
EXTRACTED_KEY * pExtractedKey;
FLMUINT uiEncLen;
FLMBYTE * pTemp;
FLMBYTE * pucBuffer = NULL;
FLMBYTE * pucSalt;
FLMUINT uiAllocSize;
NICI_PARAMETER_INFO * pParmInfo = NULL;
FLMBYTE * pucTempPtr;
f_mutexLock( m_hMutex);
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
// Extract the SALT from the key buffer.
pucSalt = pszExtractedKey + (ui32Length - SALT_SZ);
ui32Length -= SALT_SZ;
// Make one allocation and point into it for the different buffers we need.
uiAllocSize = ui32Length +
sizeof(NICI_PARAMETER_DATA) * 2 + sizeof(FLMUINT32);
if (RC_BAD( rc = f_calloc( uiAllocSize, &pucBuffer)))
{
goto Exit;
}
pParmInfo = (NICI_PARAMETER_INFO *)(pucBuffer + ui32Length);
// Now to decrypt the buffer.
algorithm.algorithm = (nuint8 *)oid_pbe;
pParmInfo->count = 2; // Two parameters
pParmInfo->parms[0].parmType = NICI_P_SALT;
pParmInfo->parms[0].u.b.len = SALT_SZ;
pParmInfo->parms[0].u.b.ptr = (nuint8 *)pucSalt;
pParmInfo->parms[1].parmType = NICI_P_COUNT;
pParmInfo->parms[1].u.value = SALT_COUNT;
algorithm.parameter = pParmInfo;
algorithm.parameterLen = sizeof(NICI_PARAMETER_DATA) * 2 + sizeof(FLMUINT32);
uiEncLen = ui32Length;
if (RC_BAD( rc = CCS_pbeDecrypt(
m_hContext,
&algorithm,
puzEncKeyPasswd,
(nuint8 *)pszExtractedKey,
ui32Length,
(nuint8 *)pucBuffer,
&uiEncLen)))
{
rc = RC_SET( NE_SFLM_PBE_DECRYPT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// For cross platform compatibility, we need to first extract the KeyType,
// FormatLen and KeyLen values then we will set them back again. They are
// stored in a specific byte order, which may not match the native order for
// referencing integers on the local platform.
pExtractedKey = (EXTRACTED_KEY *)pucBuffer;
pucTempPtr = pucBuffer;
pExtractedKey->uiKeyType = FB2UD( pucTempPtr);
pucTempPtr += 4;
pExtractedKey->uiFormatLen = FB2UD( pucTempPtr);
pucTempPtr += 4;
pExtractedKey->uiKeyLen = FB2UD( pucTempPtr);
pucTempPtr += 4;
m_uiEncKeySize = FB2UD( pucTempPtr);
// Calculate a SHA1 checksum.
algorithm.algorithm = (nuint8 *)oid_sha1;
algorithm.parameter = NULL;
algorithm.parameterLen = 0;
if (RC_BAD( rc = CCS_DigestInit(
m_hContext,
&algorithm)))
{
rc = RC_SET( NE_SFLM_DIGEST_INIT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
pTemp = (FLMBYTE *)&pExtractedKey[ 1];
if (RC_BAD( rc = CCS_Digest(
m_hContext,
(nuint8 *)pTemp,
pExtractedKey->uiFormatLen +
pExtractedKey->uiKeyLen,
(nuint8 *)ucDigest,
&uiDigestLen)))
{
rc = RC_SET( NE_SFLM_DIGEST_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
flmAssert( uiDigestLen == sizeof( ucDigest));
// Now compare the two digests. They must be equal!
pTemp += pExtractedKey->uiKeyLen + pExtractedKey->uiFormatLen;
if (f_memcmp( pTemp, ucDigest, uiDigestLen))
{
rc = RC_SET( NE_SFLM_INVALID_ENCKEY_CRC);
goto Exit;
}
pucFormat = (FLMBYTE *)&pExtractedKey[1]; // Point to the format
pKey = pucFormat + pExtractedKey->uiFormatLen; // Point to the key.
uiIndx = 0;
f_memset( &keyAttr[0], 0, sizeof(NICI_ATTRIBUTE) * 7);
switch (pExtractedKey->uiKeyType)
{
case NICI_K_AES:
{
/* Set key attributes */
uiIndx = 0;
keyAttr[uiIndx].type = NICI_A_KEY_TYPE;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = NICI_K_AES;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_FORMAT;
keyAttr[uiIndx].u.v.valuePtr = pucFormat;
keyAttr[uiIndx].u.v.valueLen = pExtractedKey->uiFormatLen;
keyAttr[uiIndx].u.v.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_USAGE;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = NICI_F_WRAP | NICI_F_UNWRAP | NICI_F_KM_ENCRYPT | NICI_F_KM_DECRYPT | NICI_F_EXTRACT | NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_SIZE;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = m_uiEncKeySize;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_VALUE;
keyAttr[uiIndx].u.v.valuePtr = pKey;
keyAttr[uiIndx].u.v.valueLen = pExtractedKey->uiKeyLen;
keyAttr[uiIndx].u.v.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_CLASS;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = NICI_O_SECRET_KEY;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_GLOBAL;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = N_TRUE;
keyAttr[uiIndx].u.f.valueInfo = 0;
break;
}
case NICI_K_DES3X:
{
/* Set key attributes */
uiIndx = 0;
keyAttr[uiIndx].type = NICI_A_KEY_TYPE;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = NICI_K_DES3X;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_FORMAT;
keyAttr[uiIndx].u.v.valuePtr = pucFormat;
keyAttr[uiIndx].u.v.valueLen = pExtractedKey->uiFormatLen;
keyAttr[uiIndx].u.v.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_USAGE;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = NICI_F_WRAP | NICI_F_UNWRAP | NICI_F_KM_ENCRYPT | NICI_F_KM_DECRYPT | NICI_F_EXTRACT | NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_SIZE;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = m_uiEncKeySize;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_KEY_VALUE;
keyAttr[uiIndx].u.v.valuePtr = pKey;
keyAttr[uiIndx].u.v.valueLen = pExtractedKey->uiKeyLen;
keyAttr[uiIndx].u.v.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_CLASS;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = NICI_O_SECRET_KEY;
keyAttr[uiIndx].u.f.valueInfo = 0;
uiIndx++;
keyAttr[uiIndx].type = NICI_A_GLOBAL;
keyAttr[uiIndx].u.f.hasValue = 1;
keyAttr[uiIndx].u.f.value = N_TRUE;
keyAttr[uiIndx].u.f.valueInfo = 0;
break;
}
default:
{
flmAssert( 0);
rc = RC_SET( NE_SFLM_NICI_INVALID_ALGORITHM);
goto Exit;
}
}
if (RC_BAD( rc = CCS_InjectKey(
m_hContext,
&keyAttr[0],
7,
&m_keyHandle)))
{
rc = RC_SET( NE_SFLM_INJECT_KEY_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
#endif
Exit:
#ifdef FLM_USE_NICI
if (pucBuffer)
{
f_free( &pucBuffer);
}
f_mutexUnlock( m_hMutex);
#endif
return(rc);
}
/****************************************************************************
Desc: getIVLen returns the correct length of the IV for the type of
algorithm.
****************************************************************************/
FLMUINT F_CCS::getIVLen()
{
#ifndef FLM_USE_NICI
return 0;
#else
switch (m_eEncAlgorithm)
{
case SFLM_AES_ENCRYPTION:
return IV_SZ;
case SFLM_DES3_ENCRYPTION:
return IV_SZ8;
default:
return 0;
}
#endif
}
/****************************************************************************
Desc: generateIV will generate a random set of bytes to be used as IV.
****************************************************************************/
RCODE F_CCS::generateIV(
FLMUINT uiIVLen,
FLMBYTE * pucIV)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( uiIVLen);
F_UNREFERENCED_PARM( pucIV);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
FLMUINT uiLoop;
NICI_ALGORITHM algorithm;
FLMBYTE oid_sha1[] = {IDV_SHA1};
FLMBOOL bLocked = FALSE;
FLMBYTE * pucIVPtr = m_ucRndIV;
FLMBYTE ucIVBuffer[ IV_SZ * 2];
FLMUINT uiIVBufferLen = sizeof(ucIVBuffer);
if (!uiIVLen)
{
goto Exit;
}
f_mutexLock( m_hMutex);
bLocked = TRUE;
/* Create NICI Context */
if ( !m_hContext)
{
if (RC_BAD( rc = CCS_CreateContext(0, &m_hContext)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
m_hContext = 0;
goto Exit;
}
}
// See if it is time to reinitialize the Random IV.
if ((m_uiIVFactor & 0x07FF) == 0)
{
// Generate the Random IV
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)&m_ucRndIV,
IV_SZ)))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Generate an adjustment factor for the IV
if (RC_BAD( rc = CCS_GetRandom(
m_hContext,
(nuint8 *)&m_uiIVFactor,
sizeof(FLMUINT))))
{
rc = RC_SET( NE_SFLM_NICI_BAD_RANDOM);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
}
// Increment each byte of the IV by the IV Factor
for( uiLoop = 0; uiLoop < IV_SZ; uiLoop++)
{
(*pucIVPtr) += (FLMBYTE)m_uiIVFactor;
pucIVPtr++;
}
// Now run the resulting IV through a SHA1 digest.
algorithm.algorithm = (nuint8 *)oid_sha1;
algorithm.parameter = NULL;
algorithm.parameterLen = 0;
if (RC_BAD( rc = CCS_DigestInit(
m_hContext,
&algorithm)))
{
rc = RC_SET( NE_SFLM_DIGEST_INIT_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
if (RC_BAD( rc = CCS_Digest(
m_hContext,
(nuint8 *)m_ucRndIV,
uiIVLen,
(nuint8 *)ucIVBuffer,
&uiIVBufferLen)))
{
rc = RC_SET( NE_SFLM_DIGEST_FAILED);
m_hContext = 0; // Context has been destroyed
goto Exit;
}
// Return the new IV!
f_memcpy( pucIV, ucIVBuffer, uiIVLen);
m_uiIVFactor++;
#endif
Exit:
#ifdef FLM_USE_NICI
if (bLocked)
{
f_mutexUnlock( m_hMutex);
}
#endif
return rc;
}
/****************************************************************************
Desc: flmDecryptBuffer - assumes aes
****************************************************************************/
RCODE flmDecryptBuffer(
FLMBYTE * pucBuffer,
FLMUINT * puiBufLen)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucBuffer);
F_UNREFERENCED_PARM( puiBufLen);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_CC_HANDLE context = 0;
NICI_ATTRIBUTE find[2];
NICI_OBJECT_HANDLE serverKeyHdl = 0;
FLMUINT uiCount;
NICI_ALGORITHM algorithm;
NICI_PARAMETER_INFO parm[1];
FLMBYTE oid_aes[] = {IDV_AES128CBC};
FLMBYTE pucIV[ IV_SZ];
/* Create NICI Context */
if (RC_BAD( rc = CCS_CreateContext(0, &context)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
goto Exit;
}
find[0].type = NICI_A_GLOBAL;
find[0].u.f.hasValue = 1;
find[0].u.f.value = 1;
find[0].u.f.valueInfo = 0;
find[1].type = NICI_A_FEATURE;
find[1].u.f.hasValue = 1;
find[1].u.f.value = NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT;
find[1].u.f.valueInfo = 0;
if (RC_BAD( rc = CCS_FindObjectsInit(context, find, 2)))
{
rc = RC_SET( NE_SFLM_NICI_FIND_INIT);
goto Exit;
}
uiCount = 1;
if (RC_BAD( rc = CCS_FindObjects(
context,
&serverKeyHdl,
&uiCount)))
{
rc = RC_SET( NE_SFLM_NICI_FIND_OBJECT);
goto Exit;
}
if (uiCount < 1)
{
rc = RC_SET( NE_SFLM_NICI_KEY_NOT_FOUND);
goto ExitCtx;
}
/*Set up alogrithm now to do AES and pading for encryption */
algorithm.algorithm = (nuint8 *)oid_aes;
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter = parm;
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
algorithm.parameter->parms[0].u.b.len = IV_SZ; /* 16-byte IV */
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)pucIV;
/* init encryption */
if (RC_BAD( rc = CCS_DataDecryptInit(
context,
&algorithm,
serverKeyHdl)))
{
rc = RC_SET( NE_SFLM_NICI_DECRYPT_INIT_FAILED);
goto Exit;
}
if (RC_BAD( rc = CCS_Decrypt(
context,
(nuint8 *)pucBuffer,
*puiBufLen,
(nuint8 *)pucBuffer,
puiBufLen)))
{
rc = RC_SET( NE_SFLM_NICI_DECRYPT_FAILED);
goto Exit;
}
ExitCtx:
CCS_DestroyContext( context);
#endif
Exit:
return rc;
}
/****************************************************************************
Desc: flmEncryptBuffer - assumes aes
****************************************************************************/
RCODE flmEncryptBuffer(
FLMBYTE * pucBuffer,
FLMUINT * puiBufLen)
{
RCODE rc = NE_SFLM_OK;
#ifndef FLM_USE_NICI
F_UNREFERENCED_PARM( pucBuffer);
F_UNREFERENCED_PARM( puiBufLen);
rc = RC_SET( NE_SFLM_UNSUPPORTED_FEATURE);
goto Exit;
#else
NICI_CC_HANDLE context = 0;
NICI_ATTRIBUTE find[2];
NICI_OBJECT_HANDLE serverKeyHdl = 0;
FLMUINT uiCount;
NICI_ALGORITHM algorithm;
NICI_PARAMETER_INFO parm[1];
FLMBYTE oid_aes[] = {IDV_AES128CBC};
FLMBYTE pucIV[ IV_SZ];
/* Create NICI Context */
if (RC_BAD( rc = CCS_CreateContext(0, &context)))
{
rc = RC_SET( NE_SFLM_NICI_CONTEXT);
goto Exit;
}
find[0].type = NICI_A_GLOBAL;
find[0].u.f.hasValue = 1;
find[0].u.f.value = 1;
find[0].u.f.valueInfo = 0;
find[1].type = NICI_A_FEATURE;
find[1].u.f.hasValue = 1;
find[1].u.f.value = NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT;
find[1].u.f.valueInfo = 0;
if (RC_BAD( rc = CCS_FindObjectsInit(context, find, 2)))
{
rc = RC_SET( NE_SFLM_NICI_FIND_INIT);
goto Exit;
}
uiCount = 1;
if (RC_BAD( rc = CCS_FindObjects(
context,
&serverKeyHdl,
&uiCount)))
{
rc = RC_SET( NE_SFLM_NICI_FIND_OBJECT);
goto Exit;
}
if (uiCount < 1)
{
rc = RC_SET( NE_SFLM_NICI_KEY_NOT_FOUND);
goto ExitCtx;
}
algorithm.algorithm = (nuint8 *)oid_aes;
algorithm.parameterLen = sizeof(algorithm.parameter->parms[0])+
sizeof(algorithm.parameter->count);
algorithm.parameter = parm;
algorithm.parameter->count = 1;
algorithm.parameter->parms[0].parmType = NICI_P_IV;
algorithm.parameter->parms[0].u.b.len = IV_SZ; /* 16-byte IV */
algorithm.parameter->parms[0].u.b.ptr = (nuint8 *)pucIV;
GetIV(pucIV, IV_SZ);
/* init encryption */
if (RC_BAD( rc = CCS_DataEncryptInit(
context,
&algorithm,
serverKeyHdl)))
{
rc = RC_SET_AND_ASSERT( NE_SFLM_NICI_ENC_INIT_FAILED);
goto Exit;
}
if (RC_BAD( rc = CCS_Encrypt(
context,
(nuint8 *)pucBuffer,
*puiBufLen,
(nuint8 *)pucBuffer,
puiBufLen)))
{
rc = RC_SET( NE_SFLM_NICI_ENCRYPT_FAILED);
goto Exit;
}
ExitCtx:
CCS_DestroyContext( context);
#endif
Exit:
return rc;
}
#ifdef FLM_USE_NICI
FSTATIC void GetIV(
FLMBYTE * pucIV,
FLMUINT //uiLen
)
{
FLMUINT uiLoop;
FLMUINT uiLoop2;
f_sprintf( (char *)pucIV, "3587903781145935");
for (uiLoop = 0; uiLoop < 100; uiLoop++)
{
for ( uiLoop2 = 0; uiLoop2 < IV_SZ; uiLoop2++)
{
pucIV[IV_SZ - uiLoop2] ^= pucIV[ uiLoop2];
pucIV[IV_SZ - uiLoop2] += pucIV[ uiLoop2];
pucIV[IV_SZ - uiLoop2] ^= pucIV[ uiLoop2];
}
}
}
#endif
#ifdef FLM_USE_NICI
#ifndef FLM_UNIX
int CCSX_SetNewIV(
int ,//MODULEID,
FLMUINT32 ,//hContext,
pnuint8 ,//IV,
nuint32 //IVLen
)
{
return(NICI_E_FUNCTION_NOT_SUPPORTED);
}
#endif
#endif