📄 keyload.c
字号:
isDlpAlgo( capabilityInfoPtr->cryptAlgo ) ? \
( ( CRYPT_PKCINFO_DLP * ) keyData )->isPublicKey : \
( ( CRYPT_PKCINFO_RSA * ) keyData )->isPublicKey;
if( !isPublicKey && contextInfoPtr->labelSize <= 0 )
return( CRYPT_ERROR_NOTINITED );
/* If it's a dummy object with keys held externally (e.g. in a crypto
device) we need a key label set in order to access the object at a
later date */
if( ( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) && \
contextInfoPtr->labelSize <= 0 )
return( CRYPT_ERROR_NOTINITED );
/* Load the key components into the context */
status = contextInfoPtr->loadKeyFunction( contextInfoPtr, keyData,
keyDataLen );
if( cryptStatusError( status ) )
return( status );
contextInfoPtr->flags |= CONTEXT_FLAG_KEY_SET | CONTEXT_FLAG_PBO;
/* Restrict the key usage to public-key-only actions if it's a public
key. DH keys act as both public and private keys so we don't
restrict their usage */
if( ( contextInfoPtr->flags & CONTEXT_FLAG_ISPUBLICKEY ) && \
( capabilityInfoPtr->cryptAlgo != CRYPT_ALGO_DH ) )
{
status = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE,
( void * ) &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusError( status ) )
return( status );
}
return( CRYPT_OK );
}
#endif /* !USE_FIPS140 */
/****************************************************************************
* *
* Key Generation Functions *
* *
****************************************************************************/
/* Generate a key into a CONTEXT_INFO structure */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int generateKeyConvFunction( INOUT CONTEXT_INFO *contextInfoPtr )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
MESSAGE_DATA msgData;
int keyLength = contextInfoPtr->ctxConv->userKeyLength, status;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( contextInfoPtr->type == CONTEXT_CONV );
/* If there's no key size specified, use the default length */
if( keyLength <= 0 )
{
status = getDefaultKeysize( contextInfoPtr, &keyLength );
if( cryptStatusError( status ) )
return( status );
}
/* If the context is implemented in a crypto device it may have the
capability to generate the key itself so if there's a keygen function
present we call this to generate the key directly into the context
rather than generating it ourselves and loading it in. Note that to
export this key we'll need to use an exporting context which is also
located in the device, since we can't access it externally */
if( capabilityInfoPtr->generateKeyFunction != NULL )
return( capabilityInfoPtr->generateKeyFunction( contextInfoPtr,
bytesToBits( keyLength ) ) );
/* Generate a random session key into the context. We load the random
data directly into the pagelocked encryption context and pass that in
as the key buffer, loadKey() won't copy the data if src == dest */
setMessageData( &msgData, contextInfoPtr->ctxConv->userKey, keyLength );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM );
if( cryptStatusError( status ) )
return( status );
return( contextInfoPtr->loadKeyFunction( contextInfoPtr,
contextInfoPtr->ctxConv->userKey, keyLength ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int generateKeyPKCFunction( INOUT CONTEXT_INFO *contextInfoPtr )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
int keyLength = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );
int status;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( contextInfoPtr->type == CONTEXT_PKC );
/* Set up supplementary key information */
contextInfoPtr->ctxPKC->pgpCreationTime = getApproxTime();
/* If there's no key size specified, use the default length */
if( keyLength <= 0 )
{
status = getDefaultKeysize( contextInfoPtr, &keyLength );
if( cryptStatusError( status ) )
return( status );
}
/* Generate the key into the context */
status = capabilityInfoPtr->generateKeyFunction( contextInfoPtr,
bytesToBits( keyLength ) );
if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) )
clearTempBignums( contextInfoPtr->ctxPKC );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int generateKeyMacFunction( INOUT CONTEXT_INFO *contextInfoPtr )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
MESSAGE_DATA msgData;
int keyLength = contextInfoPtr->ctxMAC->userKeyLength, status;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_MAC );
/* If there's no key size specified, use the default length */
if( keyLength <= 0 )
{
status = getDefaultKeysize( contextInfoPtr, &keyLength );
if( cryptStatusError( status ) )
return( status );
}
/* If the context is implemented in a crypto device it may have the
capability to generate the key itself so if there's a keygen function
present we call this to generate the key directly into the context
rather than generating it ourselves and loading it in. Note that to
export this key we'll need to use an exporting context which is also
located in the device, since we can't access it externally */
if( capabilityInfoPtr->generateKeyFunction != NULL )
{
return( capabilityInfoPtr->generateKeyFunction( contextInfoPtr,
bytesToBits( keyLength ) ) );
}
/* Generate a random session key into the context. We load the random
data directly into the pagelocked encryption context and pass that in
as the key buffer, loadKey() won't copy the data if src == dest */
setMessageData( &msgData, contextInfoPtr->ctxMAC->userKey, keyLength );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM );
if( cryptStatusError( status ) )
return( status );
return( contextInfoPtr->loadKeyFunction( contextInfoPtr,
contextInfoPtr->ctxMAC->userKey, keyLength ) );
}
/****************************************************************************
* *
* Key Derivation Functions *
* *
****************************************************************************/
/* Derive a key into a context from a user-supplied keying value */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int deriveKey( INOUT CONTEXT_INFO *contextInfoPtr,
IN_BUFFER( keyValueLen ) const void *keyValue,
IN_LENGTH_SHORT const int keyValueLen )
{
CRYPT_ALGO_TYPE hmacAlgo;
MECHANISM_DERIVE_INFO mechanismInfo;
static const MAP_TABLE mapTbl[] = {
{ CRYPT_ALGO_MD5, CRYPT_ALGO_HMAC_MD5 },
{ CRYPT_ALGO_SHA1, CRYPT_ALGO_HMAC_SHA1 },
{ CRYPT_ALGO_RIPEMD160, CRYPT_ALGO_HMAC_RIPEMD160 },
{ CRYPT_ALGO_SHA2, CRYPT_ALGO_HMAC_SHA2 },
{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
};
int value = DUMMY_INIT, status;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isReadPtr( keyValue, keyValueLen ) );
REQUIRES( contextInfoPtr->type == CONTEXT_CONV || \
contextInfoPtr->type == CONTEXT_MAC );
REQUIRES( needsKey( contextInfoPtr ) );
REQUIRES( keyValueLen > 0 && keyValueLen < MAX_INTLENGTH_SHORT );
/* If it's a persistent context we need to have a key label set before
we can continue */
if( ( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) && \
contextInfoPtr->labelSize <= 0 )
return( CRYPT_ERROR_NOTINITED );
/* Set up various derivation parameters if they're not already set */
status = krnlSendMessage( contextInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE, &hmacAlgo,
CRYPT_OPTION_ENCR_HASH );
if( cryptStatusOK( status ) )
status = mapValue( hmacAlgo, &value, mapTbl,
FAILSAFE_ARRAYSIZE( mapTbl, MAP_TABLE ) );
if( cryptStatusError( status ) )
return( status );
hmacAlgo = value;
if( contextInfoPtr->type == CONTEXT_CONV )
{
CONV_INFO *convInfo = contextInfoPtr->ctxConv;
int keySize = convInfo->userKeyLength;
if( keySize <= 0 )
{
/* There's no key size specified, use the default length */
status = getDefaultKeysize( contextInfoPtr, &keySize );
if( cryptStatusError( status ) )
return( status );
}
if( convInfo->saltLength <= 0 )
{
MESSAGE_DATA nonceMsgData;
setMessageData( &nonceMsgData, convInfo->salt, PKCS5_SALT_SIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &nonceMsgData,
CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( cryptStatusError( status ) )
return( status );
convInfo->saltLength = PKCS5_SALT_SIZE;
}
convInfo->keySetupAlgorithm = hmacAlgo;
setMechanismDeriveInfo( &mechanismInfo, convInfo->userKey, keySize,
keyValue, keyValueLen,
convInfo->keySetupAlgorithm,
convInfo->salt, convInfo->saltLength,
convInfo->keySetupIterations );
if( mechanismInfo.iterations <= 0 )
{
status = krnlSendMessage( contextInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE,
&mechanismInfo.iterations,
CRYPT_OPTION_KEYING_ITERATIONS );
if( cryptStatusError( status ) )
return( status );
convInfo->keySetupIterations = mechanismInfo.iterations;
}
}
else
{
MAC_INFO *macInfo = contextInfoPtr->ctxMAC;
int keySize = macInfo->userKeyLength;
if( keySize <= 0 )
{
/* There's no key size specified, use the default length */
status = getDefaultKeysize( contextInfoPtr, &keySize );
if( cryptStatusError( status ) )
return( status );
}
if( macInfo->saltLength <= 0 )
{
MESSAGE_DATA nonceMsgData;
setMessageData( &nonceMsgData, macInfo->salt, PKCS5_SALT_SIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &nonceMsgData,
CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( cryptStatusError( status ) )
return( status );
macInfo->saltLength = PKCS5_SALT_SIZE;
}
contextInfoPtr->ctxConv->keySetupAlgorithm = hmacAlgo;
setMechanismDeriveInfo( &mechanismInfo, macInfo->userKey, keySize,
keyValue, keyValueLen,
macInfo->keySetupAlgorithm,
macInfo->salt, macInfo->saltLength,
macInfo->keySetupIterations );
if( mechanismInfo.iterations <= 0 )
{
status = krnlSendMessage( contextInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE,
&mechanismInfo.iterations,
CRYPT_OPTION_KEYING_ITERATIONS );
if( cryptStatusError( status ) )
return( status );
macInfo->keySetupIterations = mechanismInfo.iterations;
}
}
/* Turn the user key into an encryption context key and load the key
into the context */
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
&mechanismInfo, MECHANISM_DERIVE_PKCS5 );
if( cryptStatusOK( status ) )
status = contextInfoPtr->loadKeyFunction( contextInfoPtr,
mechanismInfo.dataOut,
mechanismInfo.dataOutLength );
if( cryptStatusOK( status ) )
contextInfoPtr->flags |= CONTEXT_FLAG_KEY_SET;
zeroise( &mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) );
return( status );
}
/****************************************************************************
* *
* Context Access Routines *
* *
****************************************************************************/
STDC_NONNULL_ARG( ( 1 ) ) \
void initKeyHandling( INOUT CONTEXT_INFO *contextInfoPtr )
{
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
/* Set the access method pointers */
switch( contextInfoPtr->type )
{
case CONTEXT_CONV:
contextInfoPtr->loadKeyFunction = loadKeyConvFunction;
contextInfoPtr->generateKeyFunction = generateKeyConvFunction;
break;
case CONTEXT_PKC:
contextInfoPtr->loadKeyFunction = loadKeyPKCFunction;
contextInfoPtr->generateKeyFunction = generateKeyPKCFunction;
break;
case CONTEXT_MAC:
contextInfoPtr->loadKeyFunction = loadKeyMacFunction;
contextInfoPtr->generateKeyFunction = generateKeyMacFunction;
break;
default:
retIntError_Void();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -