git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@650 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2432 lines
53 KiB
C++
2432 lines
53 KiB
C++
//-------------------------------------------------------------------------
|
|
// Desc: Encryption/decryption methods for interfacing to NICI.
|
|
// 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: f_nici.cpp 12334 2006-01-23 12:45:35 -0700 (Mon, 23 Jan 2006) dsanders $
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "flaimsys.h"
|
|
|
|
#ifdef FLM_USE_NICI
|
|
FSTATIC void GetIV(
|
|
FLMBYTE * pucIV,
|
|
FLMUINT uiLen);
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Desc: wrapNiciKey - Save the wrapped key in m_pKey. NOTE: Make sure
|
|
there is a buffer allocated for the wrapped key (m_pucWrappedKey).
|
|
****************************************************************************/
|
|
F_CCS::~F_CCS()
|
|
{
|
|
|
|
if (m_hMutex != F_MUTEX_NULL)
|
|
{
|
|
f_mutexDestroy( &m_hMutex);
|
|
}
|
|
|
|
#ifdef FLM_USE_NICI
|
|
if ( m_keyHandle)
|
|
{
|
|
NICI_CC_HANDLE context = 0;
|
|
|
|
// Create NICI Context
|
|
|
|
if( RC_OK( CCS_CreateContext(0, &context)))
|
|
{
|
|
// Get rid of the key handle.
|
|
|
|
CCS_DestroyObject( context, m_keyHandle);
|
|
CCS_DestroyContext( context);
|
|
}
|
|
else
|
|
{
|
|
flmAssert( 0);
|
|
}
|
|
}
|
|
#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 = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( ppucWrappedKey);
|
|
F_UNREFERENCED_PARM( pui32Length);
|
|
F_UNREFERENCED_PARM( masterWrappingKey);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context =0;
|
|
NICI_ATTRIBUTE wKey;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_PARAMETER_INFO parm[1];
|
|
FLMBYTE oid_aes[] = {IDV_AES128CBC};
|
|
FLMBYTE oid_3des[] = {IDV_DES_EDE3_CBCPadIV8};
|
|
FLMBYTE oid_des[] = {IDV_DES_CBCPadIV8};
|
|
NICI_OBJECT_HANDLE wrappingKeyHandle;
|
|
|
|
if( masterWrappingKey)
|
|
{
|
|
wrappingKeyHandle = masterWrappingKey;
|
|
}
|
|
else
|
|
{
|
|
if( RC_BAD( rc = getWrappingKey( &wrappingKeyHandle)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
f_memset( &wKey, 0, sizeof( NICI_ATTRIBUTE));
|
|
|
|
wKey.type = NICI_A_KEY_TYPE;
|
|
if( CCS_GetAttributeValue( context, wrappingKeyHandle, &wKey, 1) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ATTRIBUTE_VALUE);
|
|
goto Exit;
|
|
}
|
|
|
|
if( !wKey.u.f.hasValue)
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_ATTRIBUTE);
|
|
goto ExitCtx;
|
|
}
|
|
|
|
switch (wKey.u.f.value)
|
|
{
|
|
case NICI_K_AES:
|
|
{
|
|
algorithm.algorithm = 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;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
break;
|
|
}
|
|
|
|
case NICI_K_DES3X:
|
|
{
|
|
algorithm.algorithm = oid_3des;
|
|
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_SZ8;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
break;
|
|
}
|
|
|
|
case NICI_K_DES:
|
|
{
|
|
// Set up alogrithm now to do DES for encryption
|
|
|
|
algorithm.algorithm = oid_des;
|
|
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_SZ8;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NICI_WRAPKEY_FAILED);
|
|
goto ExitCtx;
|
|
}
|
|
}
|
|
|
|
// We should be able to call this with NULL for the wrapped
|
|
// key, to get the length.
|
|
|
|
if( CCS_WrapKey( context, &algorithm, NICI_KM_UNSPECIFIED, 0,
|
|
wrappingKeyHandle, m_keyHandle, NULL, (NICI_ULONG *)pui32Length) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_WRAPKEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = f_calloc( *pui32Length, ppucWrappedKey)))
|
|
{
|
|
goto ExitCtx;
|
|
}
|
|
|
|
if( CCS_WrapKey( context, &algorithm, NICI_KM_UNSPECIFIED, 0,
|
|
wrappingKeyHandle, m_keyHandle, *ppucWrappedKey,
|
|
(NICI_ULONG *)pui32Length) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_WRAPKEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
ExitCtx:
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::unwrapKey(
|
|
FLMBYTE * pucWrappedKey,
|
|
FLMUINT32 ui32WrappedKeyLength,
|
|
NICI_OBJECT_HANDLE masterWrappingKey)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucWrappedKey);
|
|
F_UNREFERENCED_PARM( ui32WrappedKeyLength);
|
|
F_UNREFERENCED_PARM( masterWrappingKey);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_OBJECT_HANDLE wrappingKeyHandle;
|
|
|
|
if( masterWrappingKey)
|
|
{
|
|
wrappingKeyHandle = masterWrappingKey;
|
|
}
|
|
else
|
|
{
|
|
if( RC_BAD( rc = getWrappingKey( &wrappingKeyHandle)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext( 0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_UnwrapKey( context, wrappingKeyHandle, pucWrappedKey,
|
|
ui32WrappedKeyLength, &m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET_AND_ASSERT( FERR_NICI_UNWRAPKEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::generateEncryptionKey( void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
|
|
switch( m_uiAlgType)
|
|
{
|
|
case FLM_NICI_AES:
|
|
{
|
|
rc = generateEncryptionKeyAES();
|
|
break;
|
|
}
|
|
|
|
case FLM_NICI_DES3:
|
|
{
|
|
rc = generateEncryptionKeyDES3();
|
|
break;
|
|
}
|
|
|
|
case FLM_NICI_DES:
|
|
{
|
|
rc = generateEncryptionKeyDES();
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NICI_INVALID_ALGORITHM);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::generateEncryptionKeyAES( void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_ATTRIBUTE keyAttr[3];
|
|
FLMUINT8 keySizeChanged;
|
|
FLMBYTE oid_aes[] = {IDV_AES128CBC};
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up algorithm
|
|
|
|
algorithm.algorithm = oid_aes;
|
|
algorithm.parameterLen = 0;
|
|
|
|
// 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 = 128;
|
|
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 key
|
|
|
|
if( CCS_GenerateKey( context, &algorithm, keyAttr, 3,
|
|
(NICI_BBOOL *)&keySizeChanged, &m_keyHandle, NICI_H_INVALID) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_GENKEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
// Generate some IV to use with this key.
|
|
|
|
if( CCS_GetRandom( context, m_pucIV, IV_SZ) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_RANDOM);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::generateEncryptionKeyDES3( void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_ATTRIBUTE keyAttr[3];
|
|
FLMUINT8 keySizeChanged;
|
|
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up algorithm
|
|
|
|
algorithm.algorithm = oid_des3;
|
|
algorithm.parameterLen = 0;
|
|
|
|
// 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 = 168;
|
|
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( CCS_GenerateKey( context, &algorithm, keyAttr, 3,
|
|
(NICI_BBOOL *)&keySizeChanged, &m_keyHandle, NICI_H_INVALID) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_GENKEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
// Generate some IV to use with this key
|
|
|
|
if( CCS_GetRandom( context, m_pucIV, IV_SZ) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_RANDOM);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::generateEncryptionKeyDES( void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_ATTRIBUTE keyAttr[3];
|
|
FLMUINT8 keySizeChanged;
|
|
FLMBYTE oid_des[] = {IDV_DES_CBC_IV8};
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up AES Algorithm
|
|
|
|
algorithm.algorithm = oid_des;
|
|
algorithm.parameterLen = 0;
|
|
|
|
// 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 = 56;
|
|
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( CCS_GenerateKey( context, &algorithm, keyAttr, 3,
|
|
(NICI_BBOOL *)&keySizeChanged, &m_keyHandle, NICI_H_INVALID) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_GENKEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
// Generate some IV to use with this key.
|
|
|
|
if( CCS_GetRandom( context, m_pucIV, IV_SZ) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_RANDOM);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::generateWrappingKey( void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_ATTRIBUTE keyAttr[6];
|
|
FLMUINT8 keySizeChanged;
|
|
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
|
|
FLMUINT uiIndx;
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up AES Algorithm
|
|
|
|
algorithm.algorithm = oid_des3;
|
|
algorithm.parameterLen = 0;
|
|
|
|
// Set up 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 = oid_des3;
|
|
keyAttr[uiIndx].u.v.valueLen = sizeof( oid_des3);
|
|
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;
|
|
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 = 168;
|
|
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;
|
|
|
|
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;
|
|
|
|
// Generate an AES wrapping key
|
|
|
|
if( CCS_GenerateKey( context, &algorithm, keyAttr, 6,
|
|
(NICI_BBOOL *)&keySizeChanged, &m_keyHandle, NICI_H_INVALID) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_GENKEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
// Generate some IV to use with this key
|
|
|
|
if (CCS_GetRandom( context, m_pucIV, IV_SZ) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_RANDOM);
|
|
goto Exit;
|
|
}
|
|
|
|
// If we generated a wrap;ping key, then this object's key handle is
|
|
// actually a wrapping key. This means that we will us it to wrap
|
|
// the other keys in the system.
|
|
|
|
m_bKeyIsWrappingKey = TRUE;
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::encryptToStore(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
|
|
switch (m_uiAlgType)
|
|
{
|
|
case FLM_NICI_AES:
|
|
{
|
|
rc = encryptToStoreAES( pucIn, uiInLen, pucOut, puiOutLen);
|
|
break;
|
|
}
|
|
case FLM_NICI_DES3:
|
|
{
|
|
rc = encryptToStoreDES3( pucIn, uiInLen, pucOut, puiOutLen);
|
|
break;
|
|
}
|
|
|
|
case FLM_NICI_DES:
|
|
{
|
|
rc = encryptToStoreDES( pucIn, uiInLen, pucOut, puiOutLen);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NICI_INVALID_ALGORITHM);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::decryptFromStore(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
|
|
switch( m_uiAlgType)
|
|
{
|
|
case FLM_NICI_AES:
|
|
{
|
|
rc = decryptFromStoreAES( pucIn, uiInLen, pucOut, puiOutLen);
|
|
break;
|
|
}
|
|
|
|
case FLM_NICI_DES3:
|
|
{
|
|
rc = decryptFromStoreDES3( pucIn, uiInLen, pucOut, puiOutLen);
|
|
break;
|
|
}
|
|
|
|
case FLM_NICI_DES:
|
|
{
|
|
rc = decryptFromStoreDES( pucIn, uiInLen, pucOut, puiOutLen);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NICI_INVALID_ALGORITHM);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::encryptToStoreAES(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_PARAMETER_INFO parm[1];
|
|
FLMBYTE oid_aes[] = {IDV_AES128CBC};
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
algorithm.algorithm = 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;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
|
|
if( CCS_DataEncryptInit(context, &algorithm, m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENC_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Encrypt( context, pucIn, uiInLen, pucOut, puiOutLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENCRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::decryptFromStoreAES(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_PARAMETER_INFO parm[1];
|
|
FLMBYTE oid_aes[] = {IDV_AES128CBC};
|
|
|
|
// Create NICI Context
|
|
|
|
if (CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
algorithm.algorithm = 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;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
|
|
// Init encryption
|
|
|
|
if (CCS_DataDecryptInit(context, &algorithm, m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Decrypt( context, pucIn, uiInLen, pucOut, puiOutLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::encryptToStoreDES3(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_PARAMETER_INFO parm[1];
|
|
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
|
|
|
|
// Create NICI Context
|
|
|
|
if (CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
algorithm.algorithm = 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;
|
|
algorithm.parameter->parms[0].u.b.len = IV_SZ8;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
|
|
// Init encryption
|
|
|
|
if (CCS_DataEncryptInit(context, &algorithm, m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENC_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Encrypt( context, pucIn, uiInLen, pucOut, puiOutLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENCRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::decryptFromStoreDES3(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_PARAMETER_INFO parm[1];
|
|
FLMBYTE oid_des3[] = {IDV_DES_EDE3_CBC_IV8};
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up alogrithm now to do triple des decryption
|
|
|
|
algorithm.algorithm = 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;
|
|
algorithm.parameter->parms[0].u.b.len = IV_SZ8;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
|
|
// Init encryption
|
|
|
|
if( CCS_DataDecryptInit(context, &algorithm, m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Decrypt( context, pucIn, uiInLen, pucOut, puiOutLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::encryptToStoreDES(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_PARAMETER_INFO parm[1];
|
|
FLMBYTE oid_des[] = {IDV_DES_CBC_IV8};
|
|
|
|
// Create NICI Context
|
|
|
|
if (CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
algorithm.algorithm = oid_des;
|
|
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_SZ8;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
|
|
// Init encryption
|
|
|
|
if( CCS_DataEncryptInit(context, &algorithm, m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENC_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Encrypt(context, pucIn, uiInLen, pucOut, puiOutLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENCRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::decryptFromStoreDES(
|
|
FLMBYTE * pucIn,
|
|
FLMUINT uiInLen,
|
|
FLMBYTE * pucOut,
|
|
FLMUINT * puiOutLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucIn);
|
|
F_UNREFERENCED_PARM( uiInLen);
|
|
F_UNREFERENCED_PARM( pucOut);
|
|
F_UNREFERENCED_PARM( puiOutLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context = 0;
|
|
NICI_ALGORITHM algorithm;
|
|
NICI_PARAMETER_INFO parm[1];
|
|
FLMBYTE oid_des[] = {IDV_DES_CBC_IV8};
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext( 0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Set up alogrithm now to do triple des decryption
|
|
|
|
algorithm.algorithm = oid_des;
|
|
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_SZ8;
|
|
algorithm.parameter->parms[0].u.b.ptr = m_pucIV;
|
|
|
|
// Init encryption
|
|
|
|
if( CCS_DataDecryptInit(context, &algorithm, m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Decrypt( context, pucIn, uiInLen, pucOut, puiOutLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE F_CCS::init(
|
|
FLMBOOL bKeyIsWrappingKey,
|
|
FLMUINT uiAlgType)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
if (m_bInitCalled)
|
|
{
|
|
flmAssert(0);
|
|
goto Exit;
|
|
}
|
|
|
|
m_bKeyIsWrappingKey = bKeyIsWrappingKey;
|
|
|
|
if (uiAlgType != FLM_NICI_AES &&
|
|
uiAlgType != FLM_NICI_DES3 &&
|
|
uiAlgType != FLM_NICI_DES)
|
|
{
|
|
rc = RC_SET( FERR_NICI_INVALID_ALGORITHM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = f_mutexCreate( &m_hMutex)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
m_uiAlgType = uiAlgType;
|
|
|
|
m_bInitCalled = TRUE;
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Pick a wrapping key that we can use to wrap and
|
|
unwrap the encryption key with.
|
|
****************************************************************************/
|
|
RCODE F_CCS::getWrappingKey(
|
|
NICI_OBJECT_HANDLE * pWrappingKeyHandle)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pWrappingKeyHandle);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_ATTRIBUTE find[2];
|
|
NICI_CC_HANDLE context =0;
|
|
FLMUINT uiCount;
|
|
|
|
// Create NICI Context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_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_AV_STORAGE;
|
|
find[1].u.f.valueInfo = 0;
|
|
|
|
if( CCS_FindObjectsInit(context, find, 2) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_FIND_INIT);
|
|
goto Exit;
|
|
}
|
|
|
|
uiCount = 1;
|
|
if (CCS_FindObjects(context, pWrappingKeyHandle, &uiCount) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_FIND_OBJECT);
|
|
goto Exit;
|
|
}
|
|
|
|
if (uiCount < 1)
|
|
{
|
|
rc = RC_SET( FERR_NICI_WRAPKEY_NOT_FOUND);
|
|
goto ExitCtx;
|
|
}
|
|
|
|
ExitCtx:
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return(rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Function used to obtain the key information in the
|
|
format that will be stored on disk.
|
|
****************************************************************************/
|
|
RCODE F_CCS::getKeyToStore(
|
|
FLMBYTE ** ppucKeyInfo,
|
|
FLMUINT32 * pui32BufLen,
|
|
const char * pszEncKeyPasswd,
|
|
F_CCS * pWrappingCcs,
|
|
FLMBOOL bBase64Encode)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( ppucKeyInfo);
|
|
F_UNREFERENCED_PARM( pui32BufLen);
|
|
F_UNREFERENCED_PARM( pszEncKeyPasswd);
|
|
F_UNREFERENCED_PARM( pWrappingCcs);
|
|
F_UNREFERENCED_PARM( bBase64Encode);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
FLMBYTE * pucTmp = NULL;
|
|
FLMBYTE * pucPtr = NULL;
|
|
void * pvB64Buffer = NULL;
|
|
FLMUINT32 ui32PaddedLength;
|
|
NICI_CC_HANDLE context = 0;
|
|
IF_PosIStream * pBufferIStream = NULL;
|
|
IF_IStream * pB64Encoder = NULL;
|
|
FLMBYTE * pucWrappedKey = NULL;
|
|
FLMUINT32 ui32WrappedKeyLen = 0;
|
|
char * pszFormattedEncKeyPasswd = NULL;
|
|
NICI_OBJECT_HANDLE wrappingKeyHandle = 0;
|
|
FLMUINT uiB64Length;
|
|
|
|
*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( FLMUINT32) +
|
|
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 (CCS_CreateContext( 0, &context))
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
pucPtr = pucTmp;
|
|
|
|
// Save a flag indicating whether the key is wrapped or encoded in
|
|
// a password.
|
|
|
|
UD2FBA( (pszEncKeyPasswd && pszEncKeyPasswd[0]) ? 1 : 0, pucPtr);
|
|
pucPtr += sizeof( FLMUINT32);
|
|
|
|
// Copy the key length.
|
|
|
|
UD2FBA(ui32WrappedKeyLen, pucPtr);
|
|
pucPtr += sizeof( FLMUINT32);
|
|
|
|
// Copy the IV too.
|
|
|
|
f_memcpy( pucPtr, m_pucIV, 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( context, pucPtr,
|
|
((FLMUINT)pucTmp + ui32PaddedLength) - (FLMUINT)pucPtr))
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_RANDOM);
|
|
goto Exit;
|
|
}
|
|
|
|
if( bBase64Encode)
|
|
{
|
|
// The resulting length will not be more than doubled.
|
|
|
|
uiB64Length = (FLMUINT)(ui32PaddedLength * 2);
|
|
if( RC_BAD( rc = f_calloc( uiB64Length, &pvB64Buffer)))
|
|
{
|
|
goto ExitCtx;
|
|
}
|
|
|
|
if( RC_BAD( rc = FlmOpenBufferIStream( (const char *)pucTmp,
|
|
ui32PaddedLength, &pBufferIStream)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = FlmOpenBase64EncoderIStream( pBufferIStream,
|
|
FALSE, &pB64Encoder)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pB64Encoder->read( pvB64Buffer,
|
|
0xFFFFFFFF, &uiB64Length)))
|
|
{
|
|
if( rc != NE_FLM_EOF_HIT)
|
|
{
|
|
goto ExitCtx;
|
|
}
|
|
|
|
rc = NE_FLM_OK;
|
|
}
|
|
|
|
flmAssert( uiB64Length < (FLMUINT)(ui32PaddedLength * 2));
|
|
|
|
((FLMBYTE *)pvB64Buffer)[ uiB64Length] = '\0';
|
|
*ppucKeyInfo = (FLMBYTE *)pvB64Buffer;
|
|
pvB64Buffer = NULL;
|
|
*pui32BufLen = (FLMUINT32)uiB64Length;
|
|
}
|
|
else
|
|
{
|
|
pucTmp[ ui32PaddedLength] = '\0';
|
|
*ppucKeyInfo = pucTmp;
|
|
*pui32BufLen = ui32PaddedLength;
|
|
pucTmp = NULL;
|
|
}
|
|
|
|
ExitCtx:
|
|
|
|
CCS_DestroyContext( context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
#ifdef FLM_USE_NICI
|
|
if (pucTmp)
|
|
{
|
|
f_free(&pucTmp);
|
|
}
|
|
|
|
if (pvB64Buffer)
|
|
{
|
|
f_free(&pvB64Buffer);
|
|
}
|
|
|
|
if (pB64Encoder)
|
|
{
|
|
pB64Encoder->Release();
|
|
}
|
|
|
|
if (pBufferIStream)
|
|
{
|
|
pBufferIStream->Release();
|
|
}
|
|
|
|
if (pucWrappedKey)
|
|
{
|
|
f_free( &pucWrappedKey);
|
|
}
|
|
|
|
if (pszFormattedEncKeyPasswd)
|
|
{
|
|
f_free( &pszFormattedEncKeyPasswd);
|
|
}
|
|
#endif
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Function used to set the key info using the binary key stored
|
|
on the disk.
|
|
****************************************************************************/
|
|
RCODE F_CCS::setKeyFromStore(
|
|
FLMBYTE * pucKeyInfo,
|
|
FLMUINT32 ui32BufLen,
|
|
const char * pszEncKeyPasswd,
|
|
F_CCS * pWrappingCcs,
|
|
FLMBOOL bBase64Encoded)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucKeyInfo);
|
|
F_UNREFERENCED_PARM( ui32BufLen);
|
|
F_UNREFERENCED_PARM( pszEncKeyPasswd);
|
|
F_UNREFERENCED_PARM( pWrappingCcs);
|
|
F_UNREFERENCED_PARM( bBase64Encoded);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
FLMBYTE * pTmpKey = pucKeyInfo;
|
|
FLMBYTE * pucTmp;
|
|
FLMBYTE * pucBuffer = NULL;
|
|
FLMBOOL bShrouded = FALSE;
|
|
FLMUINT uiLength;
|
|
FLMBYTE * pucKeyBuf = NULL;
|
|
char * pszFormattedEncKeyPasswd = NULL;
|
|
NICI_OBJECT_HANDLE wrappingKeyHandle = 0;
|
|
|
|
if (pWrappingCcs)
|
|
{
|
|
flmAssert(m_bKeyIsWrappingKey == FALSE);
|
|
wrappingKeyHandle = pWrappingCcs->m_keyHandle;
|
|
}
|
|
|
|
|
|
if (bBase64Encoded)
|
|
{
|
|
F_BufferIStream bufferStream;
|
|
{
|
|
F_Base64DecoderIStream B64Decoder;
|
|
|
|
// Need a temporary buffer to translate the Base64 encoded buffer into
|
|
|
|
if (RC_BAD( rc = f_alloc( ui32BufLen, &pucKeyBuf)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = bufferStream.open( (const char *)pTmpKey, ui32BufLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = B64Decoder.open( &bufferStream)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Buffer is Base64 encoded. We must first decode it.
|
|
|
|
// Decode the buffer
|
|
|
|
if( RC_BAD( rc = B64Decoder.read(
|
|
(void *)pucKeyBuf, ui32BufLen, &uiLength)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pucTmp = pucKeyBuf;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Buffer is not base 64 encoded
|
|
|
|
pucTmp = pTmpKey;
|
|
}
|
|
|
|
// Extract the fields from the buffer
|
|
|
|
bShrouded = FB2UD( pucTmp);
|
|
pucTmp += sizeof( FLMUINT32);
|
|
|
|
// Actual length - note that the passed buffer is padded to 16 byte boundary.
|
|
|
|
uiLength = FB2UD( pucTmp);
|
|
pucTmp += sizeof( FLMUINT32);
|
|
|
|
// Get the IV
|
|
|
|
f_memcpy( m_pucIV, pucTmp, IV_SZ);
|
|
pucTmp += IV_SZ;
|
|
|
|
// Need another temporary buffer to hold the encrypted / shrouded key.
|
|
|
|
if (RC_BAD( rc = f_alloc( uiLength, &pucBuffer)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
f_memcpy( pucBuffer, pucTmp, uiLength);
|
|
|
|
if (bShrouded)
|
|
{
|
|
if (pszEncKeyPasswd == NULL)
|
|
{
|
|
rc = RC_SET( FERR_REQUIRE_PASSWD);
|
|
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, (FLMUINT32)uiLength,
|
|
(FLMUNICODE *)pszFormattedEncKeyPasswd)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pszEncKeyPasswd)
|
|
{
|
|
flmAssert( pszEncKeyPasswd[0] == '\0');
|
|
}
|
|
|
|
// Unwrap the key. The Key handle is always store in m_keyHandle.
|
|
|
|
if (RC_BAD( rc = unwrapKey( pucBuffer, (FLMUINT32)uiLength, 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;
|
|
} EXTRACTED_KEY;
|
|
|
|
/****************************************************************************
|
|
Desc: 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 = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( ppucExtractedKey);
|
|
F_UNREFERENCED_PARM( pui32Length);
|
|
F_UNREFERENCED_PARM( puzEncKeyPasswd);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context =0;
|
|
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;
|
|
|
|
// Create NICI Context
|
|
|
|
if (CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
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 (CCS_GetAttributeValue(context, m_keyHandle, &attr[0], 2) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ATTRIBUTE_VALUE);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!attr[0].u.f.hasValue)
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_ATTRIBUTE);
|
|
goto ExitCcs;
|
|
}
|
|
|
|
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;
|
|
keyAttr[uiIndx].u.v.valueLen = 16;
|
|
|
|
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:
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NICI_INVALID_ALGORITHM);
|
|
goto ExitCcs;
|
|
}
|
|
}
|
|
|
|
// Make one allocation that we can then use to hold several different things
|
|
|
|
uiBufferSize = sizeof( EXTRACTED_KEY) + attr[1].u.v.valueLen +
|
|
keyAttr[0].u.v.valueLen + sizeof (ucDigest);
|
|
uiAllocSize = uiBufferSize + SALT_SZ +
|
|
(sizeof( NICI_PARAMETER_DATA) * 2) + sizeof( FLMUINT32);
|
|
|
|
// 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 ExitCcs;
|
|
}
|
|
|
|
keyAttr[1].u.v.valuePtr = (FLMBYTE *)&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 (CCS_ExtractKey( context, m_keyHandle, &keyAttr[0], 2) != 0)
|
|
{
|
|
rc = RC_SET( FERR_EXTRACT_KEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
// Calculate a SHA1 checksum.
|
|
|
|
algorithm.algorithm = oid_sha1;
|
|
algorithm.parameter = NULL;
|
|
algorithm.parameterLen = 0;
|
|
|
|
if (CCS_DigestInit( context, &algorithm) != 0)
|
|
{
|
|
rc = RC_SET( FERR_DIGEST_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Digest( context, pucFormat,
|
|
keyAttr[0].u.v.valueLen + attr[1].u.v.valueLen, ucDigest,
|
|
&uiDigestLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_DIGEST_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
flmAssert( uiDigestLen == sizeof( ucDigest));
|
|
|
|
pucTempPtr = (FLMBYTE *)pExtractedKey;
|
|
|
|
UD2FBA( attr[0].u.f.value, pucTempPtr);
|
|
pucTempPtr += 4;
|
|
|
|
UD2FBA( attr[1].u.v.valueLen, pucTempPtr);
|
|
pucTempPtr += 4;
|
|
|
|
UD2FBA( keyAttr[0].u.v.valueLen, pucTempPtr);
|
|
|
|
// Point to the digest ...
|
|
|
|
pTemp = (FLMBYTE *)&pExtractedKey[1] +
|
|
attr[1].u.v.valueLen +
|
|
keyAttr[0].u.v.valueLen;
|
|
f_memcpy( pTemp, ucDigest, uiDigestLen);
|
|
|
|
// Generate some salt.
|
|
|
|
if (CCS_GetRandom( context, pucSalt, SALT_SZ) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_BAD_RANDOM);
|
|
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 ExitCcs;
|
|
}
|
|
|
|
// Now to encrypt the buffer.
|
|
|
|
algorithm.algorithm = oid_pbe;
|
|
|
|
pParmInfo->count = 2;
|
|
|
|
pParmInfo->parms[0].parmType = NICI_P_SALT;
|
|
pParmInfo->parms[0].u.b.len = SALT_SZ;
|
|
pParmInfo->parms[0].u.b.ptr = 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( CCS_pbeEncrypt( context, &algorithm, puzEncKeyPasswd,
|
|
(FLMBYTE *)pExtractedKey, uiBufferSize, pTemp, &uiEncLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_PBE_ENCRYPT_FAILED);
|
|
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;
|
|
|
|
ExitCcs:
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
#ifdef FLM_USE_NICI
|
|
if (pTemp)
|
|
{
|
|
f_free( &pTemp);
|
|
}
|
|
|
|
if (pucKey)
|
|
{
|
|
f_free( &pExtractedKey);
|
|
}
|
|
#endif
|
|
return(rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Inject the encrypting key using the supplied password.
|
|
****************************************************************************/
|
|
RCODE F_CCS::injectKey(
|
|
FLMBYTE * pszExtractedKey,
|
|
FLMUINT32 ui32Length,
|
|
FLMUNICODE * puzEncKeyPasswd)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pszExtractedKey);
|
|
F_UNREFERENCED_PARM( ui32Length);
|
|
F_UNREFERENCED_PARM( puzEncKeyPasswd);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_CC_HANDLE context =0;
|
|
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;
|
|
FLMUINT uiKeyType;
|
|
FLMUINT uiFormatLen;
|
|
FLMUINT uiKeyLen;
|
|
|
|
// 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);
|
|
|
|
// Create NICI context
|
|
|
|
if( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_CONTEXT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Now to decrypt the buffer.
|
|
|
|
algorithm.algorithm = oid_pbe;
|
|
|
|
pParmInfo->count = 2;
|
|
|
|
pParmInfo->parms[0].parmType = NICI_P_SALT;
|
|
pParmInfo->parms[0].u.b.len = SALT_SZ;
|
|
pParmInfo->parms[0].u.b.ptr = 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( CCS_pbeDecrypt( context, &algorithm, puzEncKeyPasswd, pszExtractedKey,
|
|
ui32Length, pucBuffer, &uiEncLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_PBE_DECRYPT_FAILED);
|
|
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;
|
|
|
|
uiKeyType = FB2UD( pucTempPtr);
|
|
pucTempPtr += 4;
|
|
pExtractedKey->uiKeyType = uiKeyType;
|
|
|
|
uiFormatLen = FB2UD( pucTempPtr);
|
|
pucTempPtr += 4;
|
|
pExtractedKey->uiFormatLen = uiFormatLen;
|
|
|
|
uiKeyLen = FB2UD( pucTempPtr);
|
|
pExtractedKey->uiKeyLen = uiKeyLen;
|
|
|
|
// Calculate a SHA1 checksum.
|
|
|
|
algorithm.algorithm = oid_sha1;
|
|
algorithm.parameter = NULL;
|
|
algorithm.parameterLen = 0;
|
|
|
|
if (CCS_DigestInit( context, &algorithm) != 0)
|
|
{
|
|
rc = RC_SET( FERR_DIGEST_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
pTemp = (FLMBYTE *)&pExtractedKey[1];
|
|
if( CCS_Digest( context, pTemp, pExtractedKey->uiFormatLen +
|
|
pExtractedKey->uiKeyLen, ucDigest, &uiDigestLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_DIGEST_FAILED);
|
|
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( FERR_INVALID_CRC);
|
|
goto ExitCcs;
|
|
}
|
|
|
|
pucFormat = (FLMBYTE *)&pExtractedKey[1];
|
|
pKey = pucFormat + pExtractedKey->uiFormatLen;
|
|
|
|
uiIndx = 0;
|
|
f_memset( &keyAttr[0], 0, sizeof(NICI_ATTRIBUTE) * 7);
|
|
|
|
switch (pExtractedKey->uiKeyType)
|
|
{
|
|
case NICI_K_AES:
|
|
{
|
|
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;
|
|
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 = 128;
|
|
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:
|
|
{
|
|
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;
|
|
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 = 168;
|
|
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_DES:
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NICI_INVALID_ALGORITHM);
|
|
goto ExitCcs;
|
|
}
|
|
}
|
|
|
|
|
|
if (CCS_InjectKey( context,
|
|
&keyAttr[0],
|
|
7,
|
|
&m_keyHandle) != 0)
|
|
{
|
|
rc = RC_SET( FERR_INJECT_KEY_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
ExitCcs:
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
#ifdef FLM_USE_NICI
|
|
if (pucBuffer)
|
|
{
|
|
f_free( &pucBuffer);
|
|
}
|
|
#endif
|
|
return(rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: flmDecryptBuffer - assumes aes
|
|
****************************************************************************/
|
|
RCODE flmDecryptBuffer(
|
|
FLMBYTE * pucBuffer,
|
|
FLMUINT * puiBufLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucBuffer);
|
|
F_UNREFERENCED_PARM( puiBufLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_ATTRIBUTE find[2];
|
|
NICI_CC_HANDLE context =0;
|
|
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( CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_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 (CCS_FindObjectsInit(context, find, 2) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_FIND_INIT);
|
|
goto Exit;
|
|
}
|
|
|
|
uiCount = 1;
|
|
if (CCS_FindObjects(context, &serverKeyHdl, &uiCount) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_FIND_OBJECT);
|
|
goto Exit;
|
|
}
|
|
|
|
if (uiCount < 1)
|
|
{
|
|
rc = RC_SET( FERR_NICI_KEY_NOT_FOUND);
|
|
goto ExitCtx;
|
|
}
|
|
|
|
// Set up alogrithm now to do AES and pading for encryption
|
|
|
|
algorithm.algorithm = 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;
|
|
algorithm.parameter->parms[0].u.b.ptr = pucIV;
|
|
|
|
// Init encryption
|
|
|
|
if( CCS_DataDecryptInit(context, &algorithm, serverKeyHdl) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if( CCS_Decrypt( context, pucBuffer, *puiBufLen, pucBuffer,
|
|
puiBufLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_DECRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
ExitCtx:
|
|
|
|
CCS_DestroyContext(context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE flmEncryptBuffer(
|
|
FLMBYTE * pucBuffer,
|
|
FLMUINT * puiBufLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
#ifndef FLM_USE_NICI
|
|
F_UNREFERENCED_PARM( pucBuffer);
|
|
F_UNREFERENCED_PARM( puiBufLen);
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
#else
|
|
NICI_ATTRIBUTE find[2];
|
|
NICI_CC_HANDLE context =0;
|
|
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 (CCS_CreateContext(0, &context) != 0)
|
|
{
|
|
rc = RC_SET( FERR_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 (CCS_FindObjectsInit(context, find, 2) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_FIND_INIT);
|
|
goto Exit;
|
|
}
|
|
|
|
uiCount = 1;
|
|
if (CCS_FindObjects(context, &serverKeyHdl, &uiCount) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_FIND_OBJECT);
|
|
goto Exit;
|
|
}
|
|
|
|
if (uiCount < 1)
|
|
{
|
|
rc = RC_SET( FERR_NICI_KEY_NOT_FOUND);
|
|
goto ExitCtx;
|
|
}
|
|
|
|
|
|
algorithm.algorithm = 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;
|
|
algorithm.parameter->parms[0].u.b.ptr = pucIV;
|
|
|
|
GetIV(pucIV, IV_SZ);
|
|
|
|
// Init encryption
|
|
|
|
if (CCS_DataEncryptInit(context, &algorithm, serverKeyHdl) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENC_INIT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if (CCS_Encrypt(context,
|
|
pucBuffer,
|
|
*puiBufLen,
|
|
pucBuffer,
|
|
puiBufLen) != 0)
|
|
{
|
|
rc = RC_SET( FERR_NICI_ENCRYPT_FAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
ExitCtx:
|
|
|
|
CCS_DestroyContext( context);
|
|
|
|
#endif
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Desc:
|
|
*****************************************************************************/
|
|
#ifdef FLM_USE_NICI
|
|
FSTATIC void GetIV(
|
|
FLMBYTE * pucIV,
|
|
FLMUINT //uiLen
|
|
)
|
|
{
|
|
FLMUINT uiLoop;
|
|
FLMUINT uiLoop2;
|
|
|
|
f_strcpy( (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
|
|
|
|
/*****************************************************************************
|
|
Desc:
|
|
*****************************************************************************/
|
|
#if defined( FLM_USE_NICI) && !defined( FLM_UNIX)
|
|
int CCSX_SetNewIV(
|
|
int , // MODULEID,
|
|
FLMUINT32 , // hContext,
|
|
pnuint8 , // IV,
|
|
nuint32) // IVLen
|
|
{
|
|
return( NICI_E_FUNCTION_NOT_SUPPORTED);
|
|
}
|
|
#endif
|