📄 resource.c
字号:
if( envelopeInfoPtr->preActionList != NULL )
return( FALSE );
}
else
if( actionListPtr != NULL )
/* A standalone action can only be (session-key based)
encryption except for de-enveloping a signed envelope,
where we can have standalone hash actions before we get
to the signature data and add post-actions */
if( !( ( actionListPtr->action == ACTION_CRYPT ) || \
( ( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
actionListPtr->action == ACTION_HASH ) ) )
return( FALSE );
/* Pre-actions can only be key exchange actions, and have to be sorted
by action group */
if( envelopeInfoPtr->preActionList != NULL )
{
actionListPtr = envelopeInfoPtr->preActionList;
while( actionListPtr != NULL && \
actionListPtr->action == ACTION_KEYEXCHANGE_PKC )
actionListPtr = actionListPtr->next;
while( actionListPtr != NULL && \
actionListPtr->action == ACTION_KEYEXCHANGE )
actionListPtr = actionListPtr->next;
return( ( actionListPtr == NULL ) ? TRUE : FALSE );
}
/* Post-actions can only be signature actions */
if( envelopeInfoPtr->postActionList != NULL )
{
for( actionListPtr = envelopeInfoPtr->postActionList;
actionListPtr != NULL; actionListPtr = actionListPtr->next )
if( actionListPtr->action != ACTION_SIGN )
return( FALSE );
return( TRUE );
}
/* A standalone action can be either a single crypt, one or more hashes,
or nothing */
if( envelopeInfoPtr->actionList == NULL )
return( TRUE );
if( envelopeInfoPtr->actionList->action == ACTION_CRYPT )
return( envelopeInfoPtr->actionList->next == NULL ? TRUE : FALSE );
for( actionListPtr = envelopeInfoPtr->preActionList;
actionListPtr != NULL; actionListPtr = actionListPtr->next )
if( actionListPtr->action != ACTION_HASH )
return( FALSE );
return( TRUE );
}
#endif /* !NDEBUG */
/****************************************************************************
* *
* Content List Management Functions *
* *
****************************************************************************/
/* Create a content list item */
CONTENT_LIST *createContentListItem( MEMPOOL_STATE memPoolState,
const CRYPT_FORMAT_TYPE formatType,
const void *object, const int objectSize,
const BOOLEAN isSigObject )
{
CONTENT_LIST *contentListItem;
if( ( contentListItem = getMemPool( memPoolState,
sizeof( CONTENT_LIST ) ) ) == NULL )
return( NULL );
memset( contentListItem, 0, sizeof( CONTENT_LIST ) );
contentListItem->formatType = formatType;
contentListItem->object = ( void * ) object;
contentListItem->objectSize = objectSize;
if( isSigObject )
{
contentListItem->flags = CONTENTLIST_ISSIGOBJ;
contentListItem->clSigInfo.iSigCheckKey = CRYPT_ERROR;
contentListItem->clSigInfo.iExtraData = CRYPT_ERROR;
}
return( contentListItem );
}
/* Add an item to the content list */
void appendContentListItem( ENVELOPE_INFO *envelopeInfoPtr,
const CONTENT_LIST *contentListItem )
{
CONTENT_LIST *contentListPtr = envelopeInfoPtr->contentList;
if( envelopeInfoPtr->contentList == NULL )
{
envelopeInfoPtr->contentList = ( CONTENT_LIST * ) contentListItem;
return;
}
/* Find the end of the list and add the new item */
while( contentListPtr->next != NULL )
contentListPtr = contentListPtr->next;
contentListPtr->next = ( CONTENT_LIST * ) contentListItem;
}
/* Delete a content list */
void deleteContentList( MEMPOOL_STATE memPoolState,
CONTENT_LIST *contentListPtr )
{
while( contentListPtr != NULL )
{
CONTENT_LIST *contentListItem = contentListPtr;
/* Destroy any attached objects if necessary */
if( contentListItem->flags & CONTENTLIST_ISSIGOBJ )
{
CONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;
if( sigInfo->iSigCheckKey != CRYPT_ERROR )
krnlSendNotifier( sigInfo->iSigCheckKey, IMESSAGE_DECREFCOUNT );
if( sigInfo->iExtraData != CRYPT_ERROR )
krnlSendNotifier( sigInfo->iExtraData, IMESSAGE_DECREFCOUNT );
}
/* Erase and free the object buffer if necessary */
contentListPtr = contentListPtr->next;
if( contentListItem->object != NULL )
{
zeroise( contentListItem->object, contentListItem->objectSize );
clFree( "deleteContentList", contentListItem->object );
}
zeroise( contentListItem, sizeof( CONTENT_LIST ) );
freeMemPool( memPoolState, contentListItem );
}
}
/****************************************************************************
* *
* Misc.Enveloping Info Management Functions *
* *
****************************************************************************/
/* Set up the encryption for an envelope */
int initEnvelopeEncryption( ENVELOPE_INFO *envelopeInfoPtr,
const CRYPT_CONTEXT cryptContext,
const CRYPT_ALGO_TYPE algorithm,
const CRYPT_MODE_TYPE mode,
const BYTE *iv, const int ivLength,
const BOOLEAN copyContext )
{
CRYPT_CONTEXT iCryptContext = cryptContext;
CRYPT_ALGO_TYPE cryptAlgo;
CRYPT_MODE_TYPE cryptMode;
RESOURCE_DATA msgData;
int blockSize, status;
/* Extract the information we need to process data */
status = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
status = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,
&cryptMode, CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,
&blockSize, CRYPT_CTXINFO_BLOCKSIZE );
if( cryptStatusError( status ) )
return( status );
/* Make sure that the context is what's required */
if( algorithm != CRYPT_UNUSED && \
( cryptAlgo != algorithm || cryptMode != mode ) )
/* This can only happen on deenveloping if the data is corrupted or
if the user is asked for a KEK and tries to supply a session key
instead */
return( CRYPT_ERROR_WRONGKEY );
/* If it's a user-supplied context, take a copy for our own use. This is
only done for non-idempotent user-supplied contexts, for everything
else we either use cryptlib's object management to handle things for
us or the context is a internal one created specifically for our own
use */
if( copyContext )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
status = krnlSendMessage( iCryptContext, IMESSAGE_CLONE, NULL,
createInfo.cryptHandle );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
iCryptContext = createInfo.cryptHandle;
}
/* Load the IV into the context and set up the encryption information for
the envelope */
if( !isStreamCipher( cryptAlgo ) )
{
if( iv != NULL )
{
int ivSize;
status = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,
&ivSize, CRYPT_CTXINFO_IVSIZE );
setMessageData( &msgData, ( void * ) iv, min( ivLength, ivSize ) );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_IV );
}
else
/* There's no IV specified, generate a new one */
status = krnlSendNotifier( iCryptContext, IMESSAGE_CTX_GENIV );
if( cryptStatusError( status ) )
{
if( copyContext )
/* Destroy the copy we created earlier */
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
return( status );
}
}
envelopeInfoPtr->iCryptContext = iCryptContext;
envelopeInfoPtr->blockSize = blockSize;
envelopeInfoPtr->blockSizeMask = ~( blockSize - 1 );
return( CRYPT_OK );
}
/* Add keyset information */
static int addKeyset( ENVELOPE_INFO *envelopeInfoPtr,
const CRYPT_ATTRIBUTE_TYPE keysetFunction,
const CRYPT_KEYSET keyset )
{
CRYPT_KEYSET *iKeysetPtr;
/* Figure out which keyset we want to set */
switch( keysetFunction )
{
case CRYPT_ENVINFO_KEYSET_ENCRYPT:
iKeysetPtr = &envelopeInfoPtr->iEncryptionKeyset;
break;
case CRYPT_ENVINFO_KEYSET_DECRYPT:
iKeysetPtr = &envelopeInfoPtr->iDecryptionKeyset;
break;
case CRYPT_ENVINFO_KEYSET_SIGCHECK:
iKeysetPtr = &envelopeInfoPtr->iSigCheckKeyset;
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL );
}
/* Make sure that the keyset hasn't already been set */
if( *iKeysetPtr != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
/* Remember the new keyset and increment its reference count */
*iKeysetPtr = keyset;
return( krnlSendNotifier( keyset, IMESSAGE_INCREFCOUNT ) );
}
/****************************************************************************
* *
* Deenveloping Information Management Functions *
* *
****************************************************************************/
/* Process CMS unauthenticated attributes. We can't handle these as
standard CMS attributes since the only thing we're likely to see here is
a countersignature, which isn't an attribute in the normal sense */
static int processUnauthAttributes( CONTENT_LIST *contentListPtr,
const void *unauthAttr,
const int unauthAttrLength )
{
STREAM stream;
int status;
UNUSED( contentListPtr );
/* Make sure that the unauthenticated attributes are OK. Normally this
is done when we import the attributes, but since we can't import
them we have to perform the check explicitly here */
status = checkObjectEncoding( unauthAttr, unauthAttrLength );
if( cryptStatusError( status ) )
return( status );
/* Process each attribute */
sMemConnect( &stream, unauthAttr, unauthAttrLength );
status = readConstructed( &stream, NULL, 1 );
while( cryptStatusOK( status ) && \
sMemDataLeft( &stream ) > MIN_CRYPT_OBJECTSIZE )
{
BYTE oid[ MAX_OID_SIZE ];
int oidLength;
/* See what we've got */
readSequence( &stream, NULL );
status = readRawObject( &stream, oid, &oidLength, MAX_OID_SIZE,
BER_OBJECT_IDENTIFIER );
if( cryptStatusOK( status ) )
status = readSet( &stream, NULL );
if( cryptStatusError( status ) )
break;
if( oidLength != sizeofOID( OID_TSP_TSTOKEN ) || \
memcmp( oid, OID_TSP_TSTOKEN, oidLength ) )
{
/* It's not a timestamp, skip it and continue */
readUniversal( &stream );
continue;
}
/* We've got a timestamp. We can't really do much with this at the
moment since although it quacks like a countersignature, in the
PKIX tradition it's subtly (and gratuitously) incompatible in
various ways, so it can't be verified as a standard
countersignature. Amusingly, the RFC actually states that this
is a stupid way to do things. Specifically, instead of using the
normal MUST/SHOULD it first states that the sensible solution to
the problem is to use a countersignature, and then goes on to
describe something that isn't a countersignature. Since this
isn't the sensible solution, it's obviously the stupid one. QED */
#if 1
readUniversal( &stream );
#else /* Alternatively, if we're being asked to return the timestamp data,
we could proceed as follows */
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
int dataSize, bufSize;
/* Find out how much data we've got */
dataSize = getStreamObjectLength( &stream );
if( cryptStatusError( dataSize ) )
return( dataSize );
if( dataSize > sMemDataLeft( &stream ) )
return( CRYPT_ERROR_OVERFLOW );
bufSize = max( dataSize + 128, MIN_BUFFER_SIZE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -