📄 resource.c
字号:
/* Create a second envelope to contain the timestamp */
setMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
return( status );
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
( void * ) &bufSize, CRYPT_ATTRIBUTE_BUFFERSIZE );
/* Push in the timestamp data */
setMessageData( &msgData, sMemBufPtr( &stream ), dataSize );
status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_ENV_PUSHDATA, &msgData, 0 );
}
if( cryptStatusError( status ) )
return( status );
/* contentListPtr->iTimestamp = createInfo.cryptHandle; */
}
#endif /* 0 */
}
sMemDisconnect( &stream );
return( status );
}
/* Import a wrapped session key */
static int importSessionKey( ENVELOPE_INFO *envelopeInfoPtr,
const CONTENT_LIST *contentListPtr,
const CRYPT_CONTEXT iImportContext,
CRYPT_CONTEXT *iSessionKeyContext )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
CONTENT_LIST *sessionKeyInfoPtr;
int status;
/* Clear the return value */
*iSessionKeyContext = CRYPT_ERROR;
/* PGP doesn't provide separate session key information with the
encrypted data but wraps it up alongside the encrypted key, so we
can't import the wrapped key into a context via the standard key
import functions but instead have to create the context as part of
the unwrap process */
if( contentListPtr->formatType == CRYPT_FORMAT_PGP )
return( iCryptImportKeyEx( contentListPtr->object,
contentListPtr->objectSize,
CRYPT_FORMAT_PGP, iImportContext,
CRYPT_UNUSED, iSessionKeyContext ) );
/* Look for the information required to recreate the session key context */
for( sessionKeyInfoPtr = envelopeInfoPtr->contentList;
sessionKeyInfoPtr != NULL && \
sessionKeyInfoPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY;
sessionKeyInfoPtr = sessionKeyInfoPtr->next );
if( sessionKeyInfoPtr == NULL )
/* We need to read more data before we can recreate the session key */
return( CRYPT_ERROR_UNDERFLOW );
/* Create the session key context and import the encrypted session key */
setMessageCreateObjectInfo( &createInfo,
sessionKeyInfoPtr->clEncrInfo.cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
&sessionKeyInfoPtr->clEncrInfo.cryptMode,
CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) )
status = iCryptImportKeyEx( contentListPtr->object,
contentListPtr->objectSize,
contentListPtr->formatType,
iImportContext, createInfo.cryptHandle,
NULL );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
*iSessionKeyContext = createInfo.cryptHandle;
return( CRYPT_OK );
}
/* Add de-enveloping information to an envelope */
static int addDeenvelopeInfo( ENVELOPE_INFO *envelopeInfoPtr,
const CRYPT_ATTRIBUTE_TYPE envInfo,
const void *value, const int valueLength )
{
CONTENT_LIST *contentListPtr = envelopeInfoPtr->contentListCurrent;
CRYPT_HANDLE cryptHandle = *( ( CRYPT_HANDLE * ) value ), iNewContext;
ACTION_LIST *actionListPtr;
int status = CRYPT_OK;
/* If it's meta-information, remember the value */
if( envInfo == CRYPT_IATTRIBUTE_ATTRONLY )
{
/* This is off by default so we should only be turning it on */
assert( ( *( int * ) value ) == TRUE );
envelopeInfoPtr->flags |= ENVELOPE_ATTRONLY;
return( CRYPT_OK );
}
/* If it's keyset information, just keep a record of it for later use */
if( envInfo == CRYPT_ENVINFO_KEYSET_SIGCHECK || \
envInfo == CRYPT_ENVINFO_KEYSET_ENCRYPT || \
envInfo == CRYPT_ENVINFO_KEYSET_DECRYPT )
return( addKeyset( envelopeInfoPtr, envInfo, cryptHandle ) );
/* If it's a hash action, the user is checking a detached sig, remember
the hash for later. In theory we should check the state of the hash
context, however PGP requires that it not be completed (since it
needs to hash further data) and everything else requires that it be
completed, but we don't know at this point whether we're processing
PGP or non-PGP data, so we can't perform any checking here */
if( envInfo == CRYPT_ENVINFO_HASH )
{
ACTION_LIST *actionListItem;
/* If there's already an action present, we can't add anything
further */
if( envelopeInfoPtr->actionList != NULL )
return( CRYPT_ERROR_INITED );
/* Add the hash as an action list item */
actionListItem = createAction( envelopeInfoPtr->memPoolState,
ACTION_HASH, cryptHandle );
if( actionListItem == NULL )
return( CRYPT_ERROR_MEMORY );
envelopeInfoPtr->actionList = actionListItem;
return( krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT ) );
}
/* Since we can add one of a multitude of necessary information types, we
need to check to make sure that what we're adding is appropriate. If
the caller hasn't tried to read the required resource information yet,
we try to match what's being added to the first information object of
the correct type */
if( contentListPtr == NULL )
{
/* Look for the first information object matching the supplied
information */
for( contentListPtr = envelopeInfoPtr->contentList;
contentListPtr != NULL && contentListPtr->envInfo != envInfo;
contentListPtr = contentListPtr->next );
if( contentListPtr == NULL )
return( CRYPT_ARGERROR_VALUE );
}
/* Make sure that the information we're adding matches the currently
required 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->envInfo != envInfo && \
!( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY && \
envInfo == CRYPT_ENVINFO_PASSWORD ) )
return( CRYPT_ARGERROR_VALUE );
/* If it's a signature object, check the signature and exit. Anything
left after this point is a keying object */
if( envInfo == CRYPT_ENVINFO_SIGNATURE )
{
CONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;
/* If we've already processed this entry, return the saved processing
result */
if( contentListPtr->flags & CONTENTLIST_PROCESSED )
return( sigInfo->processingResult );
/* Find the hash action we need to check this signature */
for( actionListPtr = envelopeInfoPtr->actionList;
actionListPtr != NULL; actionListPtr = actionListPtr->next )
{
int cryptAlgo;
/* Check to see if it's the one we want */
if( cryptStatusOK( \
krnlSendMessage( actionListPtr->iCryptHandle,
IMESSAGE_GETATTRIBUTE, &cryptAlgo,
CRYPT_CTXINFO_ALGO ) ) && \
cryptAlgo == sigInfo->hashAlgo )
break;
}
/* If we can't find a hash action to match this signature, return a
bad signature error since something must have altered the
algorithm ID for the hash */
if( actionListPtr == NULL || actionListPtr->action != ACTION_HASH )
{
contentListPtr->flags |= CONTENTLIST_PROCESSED;
sigInfo->processingResult = CRYPT_ERROR_SIGNATURE;
return( CRYPT_ERROR_SIGNATURE );
}
/* Check the signature */
if( contentListPtr->formatType == CRYPT_FORMAT_CMS )
{
/* If it's CMS signed data then the sig.check key should be
included with the signed data as a cert chain, however it's
possible (though unlikely) that the certs may be unrelated to
the signature, in which case the caller will have provided
the sig.check key from an external source */
status = iCryptCheckSignatureEx( contentListPtr->object,
contentListPtr->objectSize, CRYPT_FORMAT_CMS,
( sigInfo->iSigCheckKey == CRYPT_ERROR ) ? \
cryptHandle : sigInfo->iSigCheckKey,
actionListPtr->iCryptHandle,
&sigInfo->iExtraData );
/* If there are authenticated attributes present we have to
perform an extra check here to make sure that the content-type
specified in the authenticated attributes matches the actual
data content type */
if( cryptStatusOK( status ) && \
sigInfo->iExtraData != CRYPT_ERROR )
{
int contentType;
status = krnlSendMessage( sigInfo->iExtraData,
IMESSAGE_GETATTRIBUTE, &contentType,
CRYPT_CERTINFO_CMS_CONTENTTYPE );
if( cryptStatusError( status ) || \
envelopeInfoPtr->contentType != contentType )
status = CRYPT_ERROR_SIGNATURE;
}
/* If there are unauthenticated attributes present, process
them */
if( cryptStatusOK( status ) && \
sigInfo->extraData2 != NULL )
status = processUnauthAttributes( contentListPtr,
sigInfo->extraData2,
sigInfo->extraData2Length );
}
else
{
status = iCryptCheckSignatureEx( contentListPtr->object,
contentListPtr->objectSize,
contentListPtr->formatType, cryptHandle,
actionListPtr->iCryptHandle, NULL );
/* 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( cryptHandle, IMESSAGE_INCREFCOUNT );
sigInfo->iSigCheckKey = cryptHandle;
if( !valueLength )
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 free it to make the
memory available for reuse */
clFree( "addDeenvelopeInfo", contentListPtr->object );
contentListPtr->object = NULL;
contentListPtr->objectSize = 0;
contentListPtr->flags |= CONTENTLIST_PROCESSED;
sigInfo->processingResult = cryptArgError( status ) ? \
CRYPT_ERROR_SIGNATURE : status;
return( status );
}
/* If we need private key information and we've been given a password,
it's the password required to decrypt the key so we treat this
specially */
if( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY && \
envInfo == CRYPT_ENVINFO_PASSWORD )
{
MESSAGE_KEYMGMT_INFO getkeyInfo;
/* 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 );
}
/* 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 * ) value, valueLength, KEYMGMT_FLAG_USAGE_CRYPT );
}
else
{
setMessageKeymgmtInfo( &getkeyInfo,
CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
contentListPtr->issuerAndSerialNumber,
contentListPtr->issuerAndSerialNumberSize,
( void * ) value, valueLength, KEYMGMT_FLAG_USAGE_CRYPT );
}
status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PRIVATEKEY );
/* If 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 */
if( status == CRYPT_OK )
{
status = addDeenvelopeInfo( envelopeInfoPtr,
CRYPT_ENVINFO_PRIVATEKEY,
&getkeyInfo.cryptHandle, 0 );
krnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
}
return( status );
}
/* If we've been given a password, create the appropriate encryption
context for it and derive the key from the password */
if( envInfo == CRYPT_ENVINFO_PASSWORD )
{
const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;
MESSAGE_CREATEOBJECT_INFO createInfo;
/* 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 );
status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
( void * ) &encrInfo->cryptMode,
CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) )
{
#ifdef USE_PGP
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
status = pgpPasswordToKey( createInfo.cryptHandle, value,
valueLength, encrInfo->keySetupAlgo,
encrInfo->saltOrIVsize > 0 ? \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -