⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 env_attr.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*					cryptlib Envelope Attribute Routines					*
*					  Copyright Peter Gutmann 1996-2007						*
*																			*
****************************************************************************/

#include "crypt.h"
#ifdef INC_ALL
  #include "envelope.h"
#else
  #include "envelope/envelope.h"
#endif /* Compiler-specific includes */

#ifdef USE_ENVELOPES

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Exit after setting extended error information */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int exitError( INOUT ENVELOPE_INFO *envelopeInfoPtr,
					  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,
					  IN_ENUM( CRYPT_ERRTYPE ) const CRYPT_ERRTYPE_TYPE errorType, 
					  IN_ERROR const int status )
	{
	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	REQUIRES( isAttribute( errorLocus ) || \
			  isInternalAttribute( errorLocus ) );
	REQUIRES( errorType > CRYPT_ERRTYPE_NONE && \
			  errorType < CRYPT_ERRTYPE_LAST );
	REQUIRES( cryptStatusError( status ) );

	setErrorInfo( envelopeInfoPtr, errorLocus, errorType );
	return( status );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int exitErrorInited( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	REQUIRES( isAttribute( errorLocus ) || \
			  isInternalAttribute( errorLocus ) );

	return( exitError( envelopeInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT, 
					   CRYPT_ERROR_INITED ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int exitErrorNotInited( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	REQUIRES( isAttribute( errorLocus ) || \
			  isInternalAttribute( errorLocus ) );

	return( exitError( envelopeInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, 
					   CRYPT_ERROR_NOTINITED ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int exitErrorNotFound( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	REQUIRES( isAttribute( errorLocus ) || \
			  isInternalAttribute( errorLocus ) );

	return( exitError( envelopeInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, 
					   CRYPT_ERROR_NOTFOUND ) );
	}

/* Reset the internal virtual cursor in a content-list item after we've 
   moved the attribute cursor */

STDC_NONNULL_ARG( ( 1 ) ) \
static void resetVirtualCursor( INOUT CONTENT_LIST *contentListPtr )
	{
	assert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );

	if( !( contentListPtr->flags & CONTENTLIST_ISSIGOBJ ) )
		return;
	contentListPtr->clSigInfo.attributeCursorEntry = \
									CRYPT_ENVINFO_SIGNATURE_RESULT;
	}

/* Move the internal virtual cursor within a content-list item */

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
static BOOLEAN moveVirtualCursor( INOUT CONTENT_LIST *contentListPtr,
								  IN_ENUM( ATTR ) const ATTR_TYPE attrGetType )
	{
	static const CRYPT_ATTRIBUTE_TYPE attributeOrderList[] = {
				CRYPT_ENVINFO_SIGNATURE_RESULT, CRYPT_ENVINFO_SIGNATURE,
				CRYPT_ENVINFO_SIGNATURE_EXTRADATA, CRYPT_ENVINFO_TIMESTAMP, 
				CRYPT_ATTRIBUTE_NONE, CRYPT_ATTRIBUTE_NONE };
	CONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;
	CRYPT_ATTRIBUTE_TYPE attributeType = sigInfo->attributeCursorEntry;
	BOOLEAN doContinue;
	int iterationCount;

	assert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
	
	REQUIRES( attrGetType == ATTR_NEXT || attrGetType == ATTR_PREV );
	REQUIRES( sigInfo->attributeCursorEntry != CRYPT_ATTRIBUTE_NONE );

	for( doContinue = TRUE, iterationCount = 0;
		 doContinue && iterationCount < FAILSAFE_ITERATIONS_SMALL;
		 iterationCount++ )
		{
		int i;

		/* Find the position of the current sub-attribute in the attribute 
		   order list and use that to get its successor/predecessor sub-
		   attribute */
		for( i = 0; 
			 attributeOrderList[ i ] != attributeType && \
				attributeOrderList[ i ] != CRYPT_ATTRIBUTE_NONE && \
				i < FAILSAFE_ARRAYSIZE( attributeOrderList, CRYPT_ATTRIBUTE_TYPE ); 
			 i++ );
		ENSURES( i < FAILSAFE_ARRAYSIZE( attributeOrderList, \
										 CRYPT_ATTRIBUTE_TYPE ) );
		if( attributeOrderList[ i ] == CRYPT_ATTRIBUTE_NONE )
			{
			/* We've reached the first/last sub-attribute within the current 
			   item/group, tell the caller that there are no more sub-
			   attributes present and they have to move on to the next 
			   group */
			return( FALSE );
			}
		if( attrGetType == ATTR_PREV )
			attributeType = ( i < 1 ) ? CRYPT_ATTRIBUTE_NONE : \
										attributeOrderList[ i - 1 ];
		else
			attributeType = attributeOrderList[ i + 1 ];
		if( attributeType == CRYPT_ATTRIBUTE_NONE )
			{
			/* We've reached the first/last sub-attribute within the current 
			   item/group, exit as before */
			return( FALSE );
			}

		/* Check whether the required sub-attribute is present.  If not, we
		   continue and try the next one */
		doContinue = FALSE;
		switch( attributeType )
			{
			case CRYPT_ENVINFO_SIGNATURE_RESULT:
				break;	/* Always present */
				
			case CRYPT_ENVINFO_SIGNATURE:
				if( sigInfo->iSigCheckKey == CRYPT_ERROR )
					doContinue = TRUE;
				break;
	
			case CRYPT_ENVINFO_SIGNATURE_EXTRADATA:
				if( sigInfo->iExtraData == CRYPT_ERROR )
					doContinue = TRUE;
				break;

			case CRYPT_ENVINFO_TIMESTAMP:
				if( sigInfo->iTimestamp == CRYPT_ERROR )
					doContinue = TRUE;
				break;

			default:
				retIntError_Boolean();
			}
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_SMALL );
	sigInfo->attributeCursorEntry = attributeType;
	
	return( TRUE );
	}

/* Callback function used to provide external access to content list-
   internal fields */

CHECK_RETVAL_PTR \
static const void *getAttrFunction( IN_OPT TYPECAST( CONTENT_LIST * ) \
										const void *attributePtr, 
									OUT_OPT_ATTRIBUTE_Z \
										CRYPT_ATTRIBUTE_TYPE *groupID, 
									OUT_OPT_ATTRIBUTE_Z \
										CRYPT_ATTRIBUTE_TYPE *attributeID, 
									OUT_OPT_ATTRIBUTE_Z \
										CRYPT_ATTRIBUTE_TYPE *instanceID,
									IN_ENUM( ATTR ) const ATTR_TYPE attrGetType )
	{
	CONTENT_LIST *contentListPtr = ( CONTENT_LIST * ) attributePtr;
	BOOLEAN subGroupMove;

	assert( contentListPtr == NULL || \
			isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
	assert( groupID == NULL || \
			isWritePtr( groupID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( attributeID == NULL || \
			isWritePtr( attributeID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( instanceID == NULL || \
			isWritePtr( instanceID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );

	REQUIRES_N( attrGetType > ATTR_NONE && attrGetType < ATTR_LAST );

	/* Clear return values */
	if( groupID != NULL )
		*groupID = CRYPT_ATTRIBUTE_NONE;
	if( attributeID != NULL )
		*attributeID = CRYPT_ATTRIBUTE_NONE;
	if( instanceID != NULL )
		*instanceID = CRYPT_ATTRIBUTE_NONE;

	/* Move to the next or previous attribute if required.  This isn't just a
	   case of following the prev/next links because some content-list items
	   contain an entire attribute group so positioning by attribute within
	   these only changes the current selection within the group (== content-
	   list item) rather than moving to the previous/next entry.  Because of 
	   this we have to special-case the code for composite items (currently 
	   only signature objects meet this definition) and allow virtual 
	   positioning within the item */
	if( contentListPtr == NULL )
		return( NULL );
	subGroupMove = ( ( attrGetType == ATTR_PREV || \
					   attrGetType == ATTR_NEXT ) && \
					 ( contentListPtr->flags & CONTENTLIST_ISSIGOBJ ) ) ? \
				   TRUE : FALSE;
	if( subGroupMove )
		subGroupMove = moveVirtualCursor( contentListPtr, attrGetType );

	/* If we're moving by group, move to the next/previous content list
	   item and reset the internal virtual cursor.  Note that we always 
	   advance the cursor to the next/prev attribute, it's up to the calling 
	   code to manage attribute by attribute vs.group by group moves */
	if( !subGroupMove && attrGetType != ATTR_CURRENT )
		{
		contentListPtr = ( attrGetType == ATTR_PREV ) ? \
						 contentListPtr->prev : contentListPtr->next;
		if( contentListPtr != NULL )
			resetVirtualCursor( contentListPtr );
		}
	if( contentListPtr == NULL )
		return( NULL );

	/* Return ID information to the caller.  We only return the group ID if
	   we've moved within the attribute group, if we've moved from one group
	   to another we leave it cleared because envelopes can contain multiple
	   groups with the same ID and returning an ID identical to the one from
	   the group that we've moved out of would make it look as if we're still 
	   within the same group.  Note that this relies on the behaviour of the
	   attribute-move functions, which first get the current group using 
	   ATTR_CURRENT and then move to the next or previous using ATTR_NEXT/
	   PREV */
	if( groupID != NULL && ( attrGetType == ATTR_CURRENT || subGroupMove ) )
		*groupID = contentListPtr->envInfo;
	if( attributeID != NULL && \
		( contentListPtr->flags & CONTENTLIST_ISSIGOBJ ) )
		*attributeID = contentListPtr->clSigInfo.attributeCursorEntry;
	return( contentListPtr );
	}

/* Instantiate a certificate chain from a collection of certificates */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int instantiateCertChain( INOUT CONTENT_LIST *contentListItem, 
								 IN_BUFFER( certChainDataLength ) \
									const void *certChainData, 
								 IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
									const int certChainDataLength )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int status;

	assert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );
	assert( isReadPtr( certChainData, certChainDataLength ) );

	REQUIRES( contentListItem->flags & CONTENTLIST_ISSIGOBJ );
	REQUIRES( certChainDataLength >= MIN_CRYPT_OBJECTSIZE && \
			  certChainDataLength < MAX_INTLENGTH_SHORT );

	/* Instantiate the certificate chain.  Since this isn't a true 
	   certificate chain (in the sense of being degenerate PKCS #7 
	   SignedData) but only a context-tagged SET OF Certificate, we notify 
	   the certificate management code of this when it performs the import */
	setMessageCreateObjectIndirectInfo( &createInfo, certChainData,
						certChainDataLength, CRYPT_ICERTTYPE_CMS_CERTSET );
	if( contentListItem->issuerAndSerialNumber == NULL )
		{
		createInfo.arg2 = CRYPT_IKEYID_KEYID;
		createInfo.strArg2 = contentListItem->keyID;
		createInfo.strArgLen2 = contentListItem->keyIDsize;
		}
	else
		{
		createInfo.arg2 = CRYPT_IKEYID_ISSUERANDSERIALNUMBER;
		createInfo.strArg2 = contentListItem->issuerAndSerialNumber;
		createInfo.strArgLen2 = contentListItem->issuerAndSerialNumberSize;
		}
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusOK( status ) )
		contentListItem->clSigInfo.iSigCheckKey = createInfo.cryptHandle;
	return( status );
	}

/* Get information on the attribute at the current attribute-cursor 
   position.  This isn't quite as simple as it sounds because trying to 
   obtain the info may require a decrypt or key-import operation in order
   to obtain it */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int getCurrentAttributeInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
									OUT_INT_Z int *valuePtr )
	{
	CONTENT_LIST *contentListItem = envelopeInfoPtr->contentListCurrent;
	MESSAGE_KEYMGMT_INFO getkeyInfo;
	int status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isWritePtr( valuePtr, sizeof( int ) ) );

	REQUIRES( contentListItem != NULL );

	/* Clear return value */
	*valuePtr = 0;

	/* If we need something other than a private key or we need a private 
	   key but there's no keyset present to fetch it from, just report what 
	   we need and exit */
	if( contentListItem->envInfo != CRYPT_ENVINFO_PRIVATEKEY || \
		envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )
		{
		*valuePtr = contentListItem->envInfo;
		return( CRYPT_OK );
		}

	/* There's a decryption keyset available, try and get the required key 
	   from it.  Even though we're accessing the key by (unique) key ID we 
	   still specify the key type preference in case there's some problem 
	   with the ID info.  This means that we return a more meaningful error 
	   message now rather than a usage-related one when we try to use the 
	   key.

	   Unlike signature check keyset access, we retry the access every time 
	   we're called because we may be talking to a device that has a trusted 
	   authentication path which is outside our control so that the first 
	   read fails if the user hasn't entered their PIN but a second read 
	   once they've entered it will succeed */
	if( contentListItem->issuerAndSerialNumber == NULL )
		{
		setMessageKeymgmtInfo( &getkeyInfo, 
						( contentListItem->formatType == CRYPT_FORMAT_PGP ) ? \
							CRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID, 
						contentListItem->keyID, contentListItem->keyIDsize, 
						NULL, 0, KEYMGMT_FLAG_USAGE_CRYPT );
		}
	else
		{
		setMessageKeymgmtInfo( &getkeyInfo, 
						CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
						contentListItem->issuerAndSerialNumber,
						contentListItem->issuerAndSerialNumberSize,
						NULL, 0, KEYMGMT_FLAG_USAGE_CRYPT );
		}
	status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset, 
							  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
							  KEYMGMT_ITEM_PRIVATEKEY );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -