📄 res_denv.c
字号:
/* If it's a format that includes signing key info remember the key
that was used to check the signature in case the user wants to
query it later */
if( contentListPtr->formatType != CRYPT_FORMAT_PGP )
{
krnlSendNotifier( sigCheckContext, IMESSAGE_INCREFCOUNT );
sigInfo->iSigCheckKey = sigCheckContext;
if( isExternalKey )
contentListPtr->flags |= CONTENTLIST_EXTERNALKEY;
}
}
/* Remember the processing result so that we don't have to repeat the
processing if queried again. Since we don't need the encoded
signature data any more after this point we can free it */
clFree( "addSignatureInfo", ( void * ) contentListPtr->object );
contentListPtr->object = NULL;
contentListPtr->objectSize = 0;
contentListPtr->flags |= CONTENTLIST_PROCESSED;
sigInfo->processingResult = cryptArgError( status ) ? \
CRYPT_ERROR_SIGNATURE : status;
return( status );
}
/* Add a password for decryption of a private key */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int addPrivkeyPasswordInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
const CONTENT_LIST *contentListPtr,
IN_BUFFER( passwordLength ) const void *password,
IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
const int passwordLength )
{
MESSAGE_KEYMGMT_INFO getkeyInfo;
int type, status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
assert( isReadPtr( password, passwordLength ) );
REQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );
/* Make sure that there's a keyset available to pull the key from */
if( envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )
{
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEYSET_DECRYPT,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Make sure that we're trying to send the password to something for
which it makes sense. Private-key sources aren't just keysets but
can also be devices, but if we're trying to send a password to a
device to get a private key then something's gone wrong since it
should be retrieved automatically from the device, which was unlocked
via a PIN or password when a session with it was established */
status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
IMESSAGE_GETATTRIBUTE, &type,
CRYPT_IATTRIBUTE_TYPE );
if( cryptStatusError( status ) || type != OBJECT_TYPE_KEYSET )
{
/* This one is very difficult to report appropriately, the best that
we can do is report the wrong key for this type of object */
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEYSET_DECRYPT,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ERROR_WRONGKEY );
}
/* Try and get the key information */
if( contentListPtr->issuerAndSerialNumber == NULL )
{
setMessageKeymgmtInfo( &getkeyInfo,
( contentListPtr->formatType == CRYPT_FORMAT_PGP ) ? \
CRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID,
contentListPtr->keyID, contentListPtr->keyIDsize,
( void * ) password, passwordLength,
KEYMGMT_FLAG_USAGE_CRYPT );
}
else
{
setMessageKeymgmtInfo( &getkeyInfo,
CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
contentListPtr->issuerAndSerialNumber,
contentListPtr->issuerAndSerialNumberSize,
( void * ) password, passwordLength,
KEYMGMT_FLAG_USAGE_CRYPT );
}
status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PRIVATEKEY );
if( cryptStatusError( status ) )
{
retExt( status,
( status, ENVELOPE_ERRINFO,
"Couldn't retrieve private key from decryption keyset" ) );
}
/* We managed to get the private key, push it into the envelope. If the
call succeeds this will import the session key and delete the
required-information list, after which we don't need the private key
any more */
status = envelopeInfoPtr->addInfo( envelopeInfoPtr,
CRYPT_ENVINFO_PRIVATEKEY,
getkeyInfo.cryptHandle );
krnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Add a decryption password */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 7 ) ) \
static int addPasswordInfo( const CONTENT_LIST *contentListPtr,
IN_BUFFER( passwordLength ) const void *password,
IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
const int passwordLength,
IN_HANDLE_OPT const CRYPT_CONTEXT iMacContext,
OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iNewContext,
IN_ENUM( CRYPT_FORMAT ) \
const CRYPT_FORMAT_TYPE formatType,
INOUT ERROR_INFO *errorInfo )
{
CRYPT_CONTEXT iCryptContext;
const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;
MESSAGE_CREATEOBJECT_INFO createInfo;
int status;
assert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
assert( isReadPtr( password, passwordLength ) );
assert( ( isHandleRangeValid( iMacContext ) && iNewContext == NULL ) || \
( iMacContext == CRYPT_UNUSED && \
isWritePtr( iNewContext, sizeof( CRYPT_CONTEXT ) ) ) );
assert( isWritePtr( errorInfo, sizeof( ENVELOPE_INFO ) ) );
REQUIRES( ( isHandleRangeValid( iMacContext ) && iNewContext == NULL ) || \
( iMacContext == CRYPT_UNUSED && iNewContext != NULL ) );
REQUIRES( formatType > CRYPT_FORMAT_NONE && \
formatType < CRYPT_FORMAT_LAST );
REQUIRES( formatType != CRYPT_FORMAT_PGP || iNewContext != NULL );
/* PGP can't perform MACing, only encryption */
/* Clear return value */
if( iNewContext != NULL )
*iNewContext = CRYPT_ERROR;
/* Create the appropriate encryption context and derive the key into it */
setMessageCreateObjectInfo( &createInfo, encrInfo->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
iCryptContext = createInfo.cryptHandle;
status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
( void * ) &encrInfo->cryptMode,
CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) )
{
#ifdef USE_PGP
if( formatType == CRYPT_FORMAT_PGP )
{
status = pgpPasswordToKey( iCryptContext, CRYPT_UNUSED,
password, passwordLength, encrInfo->keySetupAlgo,
( encrInfo->saltOrIVsize > 0 ) ? \
encrInfo->saltOrIV : NULL, encrInfo->saltOrIVsize,
encrInfo->keySetupIterations );
}
else
#endif /* USE_PGP */
{
MESSAGE_DATA msgData;
/* Load the derivation information into the context */
status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
( void * ) &encrInfo->keySetupIterations,
CRYPT_CTXINFO_KEYING_ITERATIONS );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) encrInfo->saltOrIV,
encrInfo->saltOrIVsize );
status = krnlSendMessage( iCryptContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) password,
passwordLength );
status = krnlSendMessage( iCryptContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_VALUE );
}
}
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, errorInfo,
"Couldn't derive key-import key from password" ) );
}
/* In PGP there isn't any encrypted session key so the context created
from the password becomes the bulk encryption context and we're done */
if( formatType == CRYPT_FORMAT_PGP )
{
*iNewContext = iCryptContext;
return( CRYPT_OK );
}
/* Recover the session key using the password context and destroy it
when we're done with it */
if( iNewContext == NULL )
{
/* The target is a MAC context (which has already been set up), load
the session key directly into it */
status = iCryptImportKey( contentListPtr->object,
contentListPtr->objectSize,
contentListPtr->formatType,
iCryptContext, iMacContext, NULL );
}
else
{
/* The target is an encryption context, recreate it from the
encrypted session key information */
status = importSessionKey( contentListPtr, iCryptContext,
iNewContext );
}
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
{
retExt( status,
( status, errorInfo,
"Couldn't recover wrapped session key" ) );
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* De-enveloping Information Management Functions *
* *
****************************************************************************/
/* Try and match what's being added to an information object in the content
list */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int matchInfoObject( OUT_PTR CONTENT_LIST **contentListPtrPtr,
const ENVELOPE_INFO *envelopeInfoPtr,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE envInfo )
{
CONTENT_LIST *contentListPtr = envelopeInfoPtr->contentListCurrent;
const BOOLEAN privateKeyFetch = \
( envInfo == CRYPT_ENVINFO_PASSWORD && \
envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR ) ? TRUE : FALSE;
int iterationCount;
assert( isWritePtr( contentListPtrPtr, sizeof( CONTENT_LIST * ) ) );
assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
REQUIRES( envInfo == CRYPT_IATTRIBUTE_ATTRONLY || \
( envInfo > CRYPT_ENVINFO_FIRST && \
envInfo < CRYPT_ENVINFO_LAST ) );
/* Clear return value */
*contentListPtrPtr = NULL;
/* If we're adding meta-information there's nothing to check */
if( envInfo == CRYPT_IATTRIBUTE_ATTRONLY || \
envInfo == CRYPT_ENVINFO_KEYSET_SIGCHECK || \
envInfo == CRYPT_ENVINFO_KEYSET_ENCRYPT || \
envInfo == CRYPT_ENVINFO_KEYSET_DECRYPT || \
envInfo == CRYPT_ENVINFO_HASH )
return( CRYPT_OK );
/* If there's already a content-list item selected, make sure that the
information that we're adding matches the current information object.
The one exception to this is that we can be passed password
information when we require a private key if the private key is
encrypted */
if( contentListPtr != NULL )
{
if( contentListPtr->envInfo != envInfo && \
!( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY && \
privateKeyFetch ) )
return( CRYPT_ARGERROR_VALUE );
*contentListPtrPtr = contentListPtr;
return( CRYPT_OK );
}
/* Look for the first information object that matches the supplied
information */
for( contentListPtr = envelopeInfoPtr->contentList, iterationCount = 0;
contentListPtr != NULL && contentListPtr->envInfo != envInfo && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
contentListPtr = contentListPtr->next, iterationCount++ );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
if( contentListPtr == NULL && privateKeyFetch )
{
/* If we didn't find a direct match and we've been given a password,
check for a private key that can (potentially) be decrypted using
the password. This requires both a keyset/device to fetch the
key from and a private key as the required info type */
for( contentListPtr = envelopeInfoPtr->contentList, iterationCount = 0;
contentListPtr != NULL && \
contentListPtr->envInfo != CRYPT_ENVINFO_PRIVATEKEY && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
contentListPtr = contentListPtr->next, iterationCount++ );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
}
if( contentListPtr == NULL )
return( CRYPT_ARGERROR_VALUE );
*contentListPtrPtr = contentListPtr;
return( CRYPT_OK );
}
/* Complete the addition of information to an envelope */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -