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

📄 env_attr.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
				attribute == CRYPT_ATTRIBUTE_CURRENT ) || 
				/* Compression = CRYPT_UNUSED, CURRENT = cursor positioning 
				   code */
			  ( value >= 0 && value < MAX_INTLENGTH ) );
	REQUIRES( isAttribute( attribute ) || \
			  isInternalAttribute( attribute ) );

	/* Generic attributes are valid for all envelope types */
	if( attribute == CRYPT_ATTRIBUTE_BUFFERSIZE )
		{
		envelopeInfoPtr->bufSize = value;
		return( CRYPT_OK );
		}

	/* If it's meta-information, process it now */
	if( attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \
		attribute == CRYPT_ATTRIBUTE_CURRENT )
		{
		const CONTENT_LIST *contentListCursor;

		/* If it's an absolute positioning code, pre-set the attribute
		   cursor if required */
		if( value == CRYPT_CURSOR_FIRST || value == CRYPT_CURSOR_LAST )
			{
			if( envelopeInfoPtr->contentList == NULL )
				return( CRYPT_ERROR_NOTFOUND );

			ENSURES( envelopeInfoPtr->contentList != NULL );

			/* If it's an absolute attribute positioning code, reset the
			   attribute cursor to the start of the list before we try to
			   move it and if it's an attribute positioning code initialise 
			   the attribute cursor if necessary */
			if( attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \
				envelopeInfoPtr->contentListCurrent == NULL )
				{
				envelopeInfoPtr->contentListCurrent = \
										envelopeInfoPtr->contentList;
				if( envelopeInfoPtr->contentListCurrent != NULL )
					resetVirtualCursor( envelopeInfoPtr->contentListCurrent );
				}

			/* If there are no attributes present, return the appropriate 
			   error code */
			if( envelopeInfoPtr->contentListCurrent == NULL )
				{
				return( ( value == CRYPT_CURSOR_FIRST || \
						  value == CRYPT_CURSOR_LAST ) ? \
							CRYPT_ERROR_NOTFOUND : \
							CRYPT_ERROR_NOTINITED );
				}
			}
		else
			{
			/* It's a relative positioning code, return a not-inited error
			   rather than a not-found error if the cursor isn't set since
			   there may be attributes present but the cursor hasn't been
			   initialised yet by selecting the first or last absolute
			   attribute */
			if( envelopeInfoPtr->contentListCurrent == NULL )
				return( CRYPT_ERROR_NOTINITED );
			}
		ENSURES( envelopeInfoPtr->contentListCurrent != NULL );

		/* Move the cursor */
		contentListCursor = \
			attributeMoveCursor( envelopeInfoPtr->contentListCurrent, 
								 getAttrFunction, attribute, value );
		if( contentListCursor == NULL )
			return( CRYPT_ERROR_NOTFOUND );
		envelopeInfoPtr->contentListCurrent = \
								( CONTENT_LIST * ) contentListCursor;
		return( CRYPT_OK );
		}

	/* In general we can't add new enveloping information once we've started
	   processing data */
	if( envelopeInfoPtr->state != STATE_PREDATA )
		{
		/* We can't add new information once we've started enveloping */
		if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
			return( CRYPT_ERROR_INITED );

		/* We can only add signature check information once we've started
		   de-enveloping */
		if( attribute != CRYPT_ENVINFO_SIGNATURE )
			return( CRYPT_ERROR_INITED );
		}

	/* If we're de-enveloping PGP data, make sure that the attribute is 
	   valid for PGP envelopes.  We can't perform this check via the ACLs 
	   because the data type isn't known at envelope creation time so 
	   there's a single generic de-envelope type for which the ACLs allow 
	   the union of all de-enveloping attribute types.  The following check 
	   weeds out the ones that don't work for PGP */
	if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
		{
		if( attribute == CRYPT_OPTION_ENCR_MAC || \
			attribute == CRYPT_ENVINFO_INTEGRITY || \
			attribute == CRYPT_ENVINFO_KEY || \
			attribute == CRYPT_ENVINFO_SESSIONKEY )
			return( CRYPT_ARGERROR_VALUE );
		if( attribute == CRYPT_ENVINFO_HASH && \
			!( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) )
			{
			/* We can add a hash if we're creating a detached signature */
			return( CRYPT_ARGERROR_VALUE );
			}
		}

	/* Since the information may not be used for quite some time after it's
	   added we do some preliminary checking here to allow us to return an
	   error code immediately rather than from some deeply-buried function an
	   indeterminate time in the future.  Since much of the checking is
	   similar, we use a table-driven check for most types and fall back to
	   custom checking for special cases */
	for( i = 0; checkTable[ i ].type != ACTION_NONE && \
				i < FAILSAFE_ARRAYSIZE( checkTable, CHECK_INFO ); i++ )
		{
		if( checkTable[ i ].type == attribute )
			{
			if( envelopeInfoPtr->usage != ACTION_NONE && \
				envelopeInfoPtr->usage != checkTable[ i ].usage )
				return( exitErrorInited( envelopeInfoPtr, attribute ) );
			usage = checkTable[ i ].usage;
			checkType = checkTable[ i ].checkType;
			break;
			}
		}
	ENSURES( i < FAILSAFE_ARRAYSIZE( checkTable, CHECK_INFO ) );
	if( usage != ACTION_NONE )
		{
		/* Make sure that the usage requirements for the item that we're 
		   about to add are consistent */
		if( envelopeInfoPtr->usage != ACTION_NONE && \
			envelopeInfoPtr->usage != usage )
			return( exitErrorInited( envelopeInfoPtr, 
									 attribute ) );
		}
	else
		{
		/* It's not a general class of action, perform special-case usage 
		   checking */
		status = checkOtherAttribute( envelopeInfoPtr, value, attribute, 
									  &usage, &checkType );
		if( cryptStatusError( status ) )
			{
			/* An attribute that's handled internally will return OK_SPECIAL 
			   to indicate that there's nothing further to do */
			if( status == OK_SPECIAL )
				return( CRYPT_OK );

			return( status );
			}
		}

	if( checkType != MESSAGE_CHECK_NONE )
		{
		/* Check the object as appropriate.  A key agreement key can also act
		   as a public key because of the way KEA works so if a check for a
		   straight public key fails we try again to see if it's a key
		   agreement key with import capabilities */
		status = krnlSendMessage( value, IMESSAGE_CHECK, NULL, checkType );
		if( status == CRYPT_ARGERROR_OBJECT && \
			attribute == CRYPT_ENVINFO_PUBLICKEY )
			status = krnlSendMessage( value, IMESSAGE_CHECK, NULL,
									  MESSAGE_CHECK_PKC_KA_IMPORT );
		if( cryptStatusError( status ) )
			return( CRYPT_ARGERROR_NUM1 );

		/* Make sure that the object corresponds to a representable algorithm
		   type.  Note that this check isn't totally foolproof on de-
		   enveloping PGP data since the user can push in the hash context 
		   before they push in the signed data (to signifiy the use of a 
		   detached signature) so it'd be checked using the default (CMS) 
		   algorithm values rather than the PGP ones */
		if( checkType == MESSAGE_CHECK_PKC_ENCRYPT || \
			checkType == MESSAGE_CHECK_PKC_DECRYPT || \
			checkType == MESSAGE_CHECK_PKC_SIGN || \
			checkType == MESSAGE_CHECK_PKC_SIGCHECK || \
			checkType == MESSAGE_CHECK_CRYPT || \
			checkType == MESSAGE_CHECK_HASH || \
			checkType == MESSAGE_CHECK_MAC )
			{
			CRYPT_ALGO_TYPE algorithm;
			CRYPT_MODE_TYPE mode = CRYPT_MODE_NONE;

			status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
									  &algorithm, CRYPT_CTXINFO_ALGO );
			if( cryptStatusOK( status ) && checkType == MESSAGE_CHECK_CRYPT )
				{
				/* It's a conventional-encryption context, get the mode as 
				   well */
				status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, 
										  &mode, CRYPT_CTXINFO_MODE );
				}
			if( cryptStatusError( status ) )
				return( CRYPT_ARGERROR_NUM1 );
			if( !envelopeInfoPtr->checkAlgo( algorithm, mode ) )
				return( CRYPT_ERROR_NOTAVAIL );
			}

		/* If we're using CMS enveloping then the object must have an 
		   initialised certificate of the correct type associated with it.  
		   Most of this will be caught by the kernel but there are a couple 
		   of special cases (e.g. an attribute certificate where the main 
		   object is a PKC context) which are missed by the general kernel 
		   checks */
		if( ( attribute == CRYPT_ENVINFO_SIGNATURE || \
			  attribute == CRYPT_ENVINFO_PUBLICKEY || \
			  attribute == CRYPT_ENVINFO_PRIVATEKEY || \
			  attribute == CRYPT_ENVINFO_ORIGINATOR ) && 
			( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \
			  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) )
			{
			int inited, certType;

			status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, &inited, 
									  CRYPT_CERTINFO_IMMUTABLE );
			if( cryptStatusError( status ) || !inited )
				return( CRYPT_ARGERROR_NUM1 );
			status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
									  &certType, CRYPT_CERTINFO_CERTTYPE );
			if( cryptStatusError( status ) ||
				( certType != CRYPT_CERTTYPE_CERTIFICATE && \
				  certType != CRYPT_CERTTYPE_CERTCHAIN ) )
				return( CRYPT_ARGERROR_NUM1 );
			}
		}

	/* Add it to the envelope */
	status = envelopeInfoPtr->addInfo( envelopeInfoPtr, attribute,
									   value );
	if( cryptStatusError( status ) )
		{
		if( status == CRYPT_ERROR_INITED )
			return( exitErrorInited( envelopeInfoPtr, attribute ) );
		return( status );
		}
	if( usage != ACTION_NONE )
		{
		/* The action was successfully added, update the usage if 
		   necessary */
		envelopeInfoPtr->usage = usage;
		}
	return( CRYPT_OK );
	}

/* Set a string attribute */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int setEnvelopeAttributeS( INOUT ENVELOPE_INFO *envelopeInfoPtr,
						   IN_BUFFER( dataLength ) const void *data,
						   IN_LENGTH const int dataLength,
						   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )
	{
	ACTION_TYPE usage = ACTION_NONE;
	int status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isReadPtr( data, dataLength ) );

	REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH );
	REQUIRES( isAttribute( attribute ) || \
			  isInternalAttribute( attribute ) );

	/* Handle the various information types */
	switch( attribute )
		{
		case CRYPT_ENVINFO_PASSWORD:
			/* Set the envelope usage type based on the fact that we've been
			   fed a password */
			if( envelopeInfoPtr->usage == ACTION_NONE )
				usage = ACTION_CRYPT;
			else
				{
				if( envelopeInfoPtr->usage != ACTION_CRYPT && \
					envelopeInfoPtr->usage != ACTION_MAC )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_PASSWORD ) );
				}

			/* In general we can't add new enveloping information once we've
			   started processing data */
			if( envelopeInfoPtr->state != STATE_PREDATA && \
				!( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
				{
				/* We can't add new information once we've started enveloping */
				return( exitErrorInited( envelopeInfoPtr, 
										 CRYPT_ENVINFO_PASSWORD ) );
				}

			/* Add it to the envelope */
			status = envelopeInfoPtr->addInfoString( envelopeInfoPtr,
								CRYPT_ENVINFO_PASSWORD, data, dataLength );
			break;

		case CRYPT_ENVINFO_RECIPIENT:
			{
			MESSAGE_KEYMGMT_INFO getkeyInfo;

			/* Set the envelope usage type based on the fact that we've been
			   fed a recipient email address */
			if( envelopeInfoPtr->usage != ACTION_NONE && \
				envelopeInfoPtr->usage != ACTION_CRYPT )
				return( CRYPT_ARGERROR_VALUE );
			usage = ACTION_CRYPT;

			/* Make sure that there's a keyset available to pull the 
			   recipient's key from */
			if( envelopeInfoPtr->iEncryptionKeyset == CRYPT_ERROR )
				return( exitErrorNotInited( envelopeInfoPtr, 
											CRYPT_ENVINFO_KEYSET_ENCRYPT ) );

			/* Try and read the recipient's key from the keyset.  Some 
			   keysets (particularly PKCS #11 devices, for which apps set 
			   the usage flags more or less at random) may not be able to 
			   differentiate between encryption and signature keys based on 
			   the information that they have.  This isn't a problem when 
			   matching a key based on a unique ID but with the use of the 
			   recipient name as the ID there could be multiple possible 
			   matches.  Before we try and use the key we therefore perform 
			   an extra check here to make sure that it really is an 
			   encryption-capable key */
			setMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_URI, data, 
								   dataLength, NULL, 0, 
								   KEYMGMT_FLAG_USAGE_CRYPT );
			status = krnlSendMessage( envelopeInfoPtr->iEncryptionKeyset,
									  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
									  KEYMGMT_ITEM_PUBLICKEY );
			if( cryptStatusOK( status ) && \
				cryptStatusError( \
					krnlSendMessage( getkeyInfo.cryptHandle, IMESSAGE_CHECK, 
									 NULL, MESSAGE_CHECK_PKC_ENCRYPT ) ) )
				{
				krnlSendNotifier( getkeyInfo.cryptHandle,
								  IMESSAGE_DECREFCOUNT );
				status = CRYPT_ERROR_NOTFOUND;
				}
			if( cryptStatusOK( status ) )
				{
				/* We got the key, add it to the envelope */
				status = envelopeInfoPtr->addInfo( envelopeInfoPtr,
												   CRYPT_ENVINFO_PUBLICKEY,
												   getkeyInfo.cryptHandle );
				krnlSendNotifier( getkeyInfo.cryptHandle,
								  IMESSAGE_DECREFCOUNT );
				}
			break;
			}

		default:
			retIntError();
		}

	if( cryptStatusError( status ) )
		{
		if( status == CRYPT_ERROR_INITED )
			return( exitErrorInited( envelopeInfoPtr, attribute ) );
		return( status );
		}
	if( usage != ACTION_NONE )
		{
		/* The action was successfully added, update the usage if 
		   necessary */
		envelopeInfoPtr->usage = usage;
		}
	return( CRYPT_OK );
	}

#endif /* USE_ENVELOPES */

⌨️ 快捷键说明

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