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

📄 cryptenv.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
			{
			CRYPT_HANDLE iCryptHandle;
			CONTENT_LIST *contentListItem = \
								envelopeInfoPtr->contentListCurrent;

			assert( contentListItem != NULL );

			/* Make sure that there's extra data present */
			iCryptHandle = \
				( messageValue == CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) ? \
					contentListItem->clSigInfo.iExtraData : \
					contentListItem->clSigInfo.iTimestamp;
			if( iCryptHandle == CRYPT_ERROR )
				return( exitErrorNotFound( envelopeInfoPtr, messageValue ) );

			/* Return it to the caller */
			krnlSendNotifier( iCryptHandle, IMESSAGE_INCREFCOUNT );
			*valuePtr = iCryptHandle;
			return( CRYPT_OK );
			}

		case CRYPT_IATTRIBUTE_ATTRONLY:
			/* If this isn't signed data, we don't know whether it's an 
			   attributes-only message or not */
			if( envelopeInfoPtr->usage != ACTION_SIGN )
				return( exitErrorNotFound( envelopeInfoPtr, 
										   CRYPT_IATTRIBUTE_ATTRONLY ) );
			*valuePtr = ( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY ) ? \
						TRUE : FALSE;
			return( CRYPT_OK );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

static int processGetAttributeS( ENVELOPE_INFO *envelopeInfoPtr,
								 void *messageDataPtr, const int messageValue )
	{
	CONTENT_LIST *contentListItem;
	int status;

	/* If we're querying something that resides in the content list, make
	   sure there's a content list present.  If it's present but nothing is
	   selected, select the first entry */
	if( messageValue == CRYPT_ENVINFO_PRIVATEKEY_LABEL && \
		envelopeInfoPtr->contentListCurrent == NULL )
		{
		if( envelopeInfoPtr->contentList == NULL )
			return( exitErrorNotFound( envelopeInfoPtr, 
									   CRYPT_ENVINFO_PRIVATEKEY_LABEL ) );
		envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentList;
		resetVirtualCursor( envelopeInfoPtr->contentListCurrent );
		}

	/* Generic attributes are valid for all envelope types */
	if( messageValue == CRYPT_ENVINFO_PRIVATEKEY_LABEL )
		{
		MESSAGE_KEYMGMT_INFO getkeyInfo;
		char label[ CRYPT_MAX_TEXTSIZE ];

		/* Make sure that the current required resource is a private key and
		   that there's a keyset available to pull the key from */
		contentListItem = envelopeInfoPtr->contentListCurrent;
		if( contentListItem->envInfo != CRYPT_ENVINFO_PRIVATEKEY )
			return( exitErrorNotFound( envelopeInfoPtr, 
									   CRYPT_ENVINFO_PRIVATEKEY_LABEL ) );
		if( envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )
			return( exitErrorNotInited( envelopeInfoPtr, 
										CRYPT_ENVINFO_KEYSET_DECRYPT ) );

		/* Try and get the key label information.  Since we're accessing the 
		   key by (unique) key ID, there's no real need to specify a 
		   preference for encryption keys */
		if( contentListItem->issuerAndSerialNumber == NULL )
			{
			setMessageKeymgmtInfo( &getkeyInfo, 
								   ( contentListItem->formatType == CRYPT_FORMAT_PGP ) ? \
								   CRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID, 
								   contentListItem->keyID,
								   contentListItem->keyIDsize,
								   label, CRYPT_MAX_TEXTSIZE,
								   KEYMGMT_FLAG_LABEL_ONLY );
			}
		else
			{
			setMessageKeymgmtInfo( &getkeyInfo, 
								   CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
								   contentListItem->issuerAndSerialNumber,
								   contentListItem->issuerAndSerialNumberSize,
								   label, CRYPT_MAX_TEXTSIZE,
								   KEYMGMT_FLAG_LABEL_ONLY );
			}
		status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
								  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
								  KEYMGMT_ITEM_PRIVATEKEY );
		if( cryptStatusOK( status ) )
			return( attributeCopy( messageDataPtr, getkeyInfo.auxInfo,
								   getkeyInfo.auxInfoLength ) );
		return( status );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

static int processSetAttribute( ENVELOPE_INFO *envelopeInfoPtr,
								void *messageDataPtr, const int messageValue )
	{
	MESSAGE_CHECK_TYPE checkType = MESSAGE_CHECK_NONE;
	ACTION_TYPE usage = ACTION_NONE;
	static const struct {
		const CRYPT_ATTRIBUTE_TYPE type;	/* Attribute type */
		const ACTION_TYPE usage;			/* Corresponding usage type */
		const MESSAGE_CHECK_TYPE checkType;	/*  and check type */
		} checkTable[] = {
#ifdef USE_COMPRESSION
		{ CRYPT_ENVINFO_COMPRESSION, ACTION_COMPRESS, MESSAGE_CHECK_NONE },
#endif /* USE_COMPRESSION */
		{ CRYPT_ENVINFO_MAC, ACTION_MAC, MESSAGE_CHECK_MAC },
		{ CRYPT_ENVINFO_KEY, ACTION_CRYPT, MESSAGE_CHECK_CRYPT },
		{ CRYPT_ENVINFO_PUBLICKEY, ACTION_CRYPT, MESSAGE_CHECK_PKC_ENCRYPT },
		{ CRYPT_ENVINFO_PRIVATEKEY, ACTION_CRYPT, MESSAGE_CHECK_PKC_DECRYPT },
		{ CRYPT_ENVINFO_SESSIONKEY, ACTION_CRYPT, MESSAGE_CHECK_CRYPT },
		{ CRYPT_ENVINFO_HASH, ACTION_SIGN, MESSAGE_CHECK_HASH },
		{ CRYPT_ENVINFO_TIMESTAMP, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_ENVINFO_DETACHEDSIGNATURE, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_IATTRIBUTE_INCLUDESIGCERT, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_IATTRIBUTE_ATTRONLY, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_ATTRIBUTE_NONE, ACTION_NONE }
		};
	const int value = *( int * ) messageDataPtr;
	int i, status;

	/* If it's an initialisation message, there's nothing to do */
	if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
		return( CRYPT_OK );

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

	/* If it's meta-information, process it now */
	if( messageValue == CRYPT_ATTRIBUTE_CURRENT_GROUP || \
		messageValue == 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 );

			/* 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( messageValue == CRYPT_ATTRIBUTE_CURRENT_GROUP || \
				envelopeInfoPtr->contentListCurrent == NULL )
				{
				envelopeInfoPtr->contentListCurrent = \
										envelopeInfoPtr->contentList;
				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 );

		/* Move the cursor */
		contentListCursor = \
			attributeMoveCursor( envelopeInfoPtr->contentListCurrent, 
								 getAttrFunction, messageValue, 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( messageValue != 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( messageValue == CRYPT_OPTION_ENCR_MAC || \
			messageValue == CRYPT_ENVINFO_MAC || \
			messageValue == CRYPT_ENVINFO_KEY || \
			messageValue == CRYPT_ENVINFO_SESSIONKEY )
			return( CRYPT_ARGERROR_VALUE );
		if( messageValue == 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++ )
		if( checkTable[ i ].type == messageValue )
			{
			if( envelopeInfoPtr->usage != ACTION_NONE && \
				envelopeInfoPtr->usage != checkTable[ i ].usage )
				return( exitErrorInited( envelopeInfoPtr, messageValue ) );
			usage = checkTable[ i ].usage;
			checkType = checkTable[ i ].checkType;
			break;
			}
	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, 
									 messageValue ) );
		}
	else
		{
		/* If it's not a general class of action, perform special-case usage
		   checking */
		switch( messageValue )
			{
			case CRYPT_OPTION_ENCR_ALGO:
				if( cryptStatusError( \
						envelopeInfoPtr->checkCryptAlgo( value, 
								isStreamCipher( value ) ? CRYPT_MODE_OFB : \
								( envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) ? \
								CRYPT_MODE_CFB : CRYPT_MODE_CBC ) ) )
					return( CRYPT_ARGERROR_VALUE );
				envelopeInfoPtr->defaultAlgo = value;
				return( CRYPT_OK );

			case CRYPT_OPTION_ENCR_HASH:
				if( cryptStatusError( \
						envelopeInfoPtr->checkHashAlgo( value ) ) )
					return( CRYPT_ARGERROR_VALUE );
				envelopeInfoPtr->defaultHash = value;
				return( CRYPT_OK );

			case CRYPT_OPTION_ENCR_MAC:
				if( cryptStatusError( \
						envelopeInfoPtr->checkHashAlgo( value ) ) )
					return( CRYPT_ARGERROR_VALUE );
				envelopeInfoPtr->defaultMAC = value;
				return( CRYPT_OK );

			case CRYPT_ENVINFO_DATASIZE:
				if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_DATASIZE ) );
				break;

			case CRYPT_ENVINFO_CONTENTTYPE:
				/* Exactly what is supposed to happen when PGP is asked to 
				   sign non-plain-data is ill-defined.  No command-line PGP 
				   option will generate this type of message, and the RFCs 
				   don't specify the behaviour (in fact RFC 1991's 
				   description of PGP signing is completely wrong).  In 
				   practice PGP hashes and signs the payload contents of a 
				   PGP literal data packet, however if there are extra layers 
				   of processing between the signing and literal packets (eg 
				   compression or encryption), what gets hashed isn't 
				   specified.  If it's always the payload of the final 
				   (literal) data packet, we'd have to be able to burrow down 
				   through arbitrary amounts of further data and processing 
				   in order to get to the payload data to hash (this also 
				   makes things like mail gateways that only allow signed 
				   messages through infeasible unless the gateway holds 
				   everyone's private key in order to get at the plaintext to 
				   hash).  Because of this problem, we disallow any attempts 
				   to set a content-type other than plain data if we're 
				   signing a PGP-format message */
				if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
					envelopeInfoPtr->usage == ACTION_SIGN && \
					value != CRYPT_CONTENT_DATA )
					return( CRYPT_ARGERROR_VALUE );

				/* For user-friendliness we allow overwriting a given content
				   type with the same type, which is useful for cases when
				   cryptlib automatically presets the type based on other
				   information */
				if( envelopeInfoPtr->contentType && \
					envelopeInfoPtr->contentType != value )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_CONTENTTYPE ) );
				break;

			case CRYPT_ENVINFO_SIGNATURE:
				checkType = \
					( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) ? \
						MESSAGE_CHECK_PKC_SIGCHECK : MESSAGE_CHECK_PKC_SIGN;
				if( envelopeInfoPtr->usage != ACTION_NONE && \
					envelopeInfoPtr->usage != ACTION_SIGN )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_SIGNATURE ) );
				if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
					envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA )
					/* See the long comment for CRYPT_ENVINFO_CONTENTTYPE */
					return( CRYPT_ARGERROR_VALUE );
				usage = ACTION_SIGN;
				break;

			case CRYPT_ENVINFO_SIGNATURE_EXTRADATA:
				if( envelopeInfoPtr->type != CRYPT_FORMAT_CMS && \
					envelopeInfoPtr->type != CRYPT_FORMAT_SMIME )

⌨️ 快捷键说明

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