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

📄 cryptenv.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
								NULL, 0, KEYMGMT_FLAG_NONE );
				}
			status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
									  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
									  KEYMGMT_ITEM_PRIVATEKEY );

			/* If we managed to get the private key (either bcause it wasn't
			   protected by a password if it's in a keyset or because it came
			   from a device), push it into the envelope.  If the call
			   succeeds, this will import the session key and delete the
			   required-information list */
			if( cryptStatusOK( status ) )
				{
				status = envelopeInfoPtr->addInfo( envelopeInfoPtr,
												   CRYPT_ENVINFO_PRIVATEKEY,
												   &getkeyInfo.cryptHandle, 0 );
				krnlSendNotifier( getkeyInfo.cryptHandle,
								  IMESSAGE_DECREFCOUNT );
				}

			/* If we got the key, there's nothing else needed.  If we didn't,
			   we still return an OK status since the caller is asking us for
			   the resource which is required and not the status of any
			   background operation that was performed while trying to obtain
			   it */
			*valuePtr = cryptStatusError( status ) ? \
							envelopeInfoPtr->contentListCurrent->envInfo : \
							CRYPT_ATTRIBUTE_NONE;
			return( CRYPT_OK );
			}

		case CRYPT_ENVINFO_CONTENTTYPE:
			if( envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )
				return( exitErrorNotFound( envelopeInfoPtr, 
										   CRYPT_ENVINFO_CONTENTTYPE ) );
			*valuePtr = envelopeInfoPtr->contentType;
			return( CRYPT_OK );

		case CRYPT_ENVINFO_DETACHEDSIGNATURE:
			/* If this isn't signed data or we haven't sorted out the content
			   details yet, we don't know whether it's a detached sig or
			   not */
			if( envelopeInfoPtr->usage != ACTION_SIGN || \
				envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )
				return( exitErrorNotFound( envelopeInfoPtr, 
										   CRYPT_ENVINFO_DETACHEDSIGNATURE ) );
			*valuePtr = ( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) ? \
						TRUE : FALSE;
			return( CRYPT_OK );

		case CRYPT_ENVINFO_SIGNATURE_RESULT:
			{
			CRYPT_HANDLE iCryptHandle;
			CONTENT_LIST *contentListItem = \
								envelopeInfoPtr->contentListCurrent;
			const CONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;
			MESSAGE_KEYMGMT_INFO getkeyInfo;

			assert( contentListItem != NULL );

			/* Make sure that the content list item is of the appropriate 
			   type, and if we've already done this one don't process it a 
			   second time.  This check is also performed by the addInfo() 
			   code, but we duplicate it here (just for the signature-result 
			   attribute) to avoid having to do an unnecessary key fetch for 
			   non-CMS signatures */
			if( contentListItem->envInfo != CRYPT_ENVINFO_SIGNATURE )
				return( exitErrorNotFound( envelopeInfoPtr, 
										   CRYPT_ENVINFO_SIGNATURE_RESULT ) );
			if( contentListItem->flags & CONTENTLIST_PROCESSED )
				{
				*valuePtr = sigInfo->processingResult;
				return( CRYPT_OK );
				}

			/* If there's an encoded cert chain present and it hasn't been
			   instantiated as a cert object yet, instantiate it now.  We
			   don't check the return value since a failure isn't fatal, we
			   can still perform the sig.check with a key pulled from a 
			   keyset */
			if( sigInfo->iSigCheckKey == CRYPT_ERROR && \
				envelopeInfoPtr->auxBuffer != NULL )
				instantiateCertChain( envelopeInfoPtr, contentListItem );

			/* If we have a key instantiated from a cert chain, use that to
			   check the signature.  In theory we could also be re-using the 
			   key from an earlier, not-completed check, however this is only 
			   retained if the check succeeds (to allow a different key to be 
			   tried if the check fails), so in practice this never occurs */
			if( sigInfo->iSigCheckKey != CRYPT_ERROR )
				{
				*valuePtr = envelopeInfoPtr->addInfo( envelopeInfoPtr,
										CRYPT_ENVINFO_SIGNATURE, 
										&sigInfo->iSigCheckKey, TRUE );
				return( CRYPT_OK );
				}

			/* We don't have a sig.check key available (for example from a 
			   CMS cert chain), make sure that there's a keyset available to 
			   pull the key from and get the key from it */
			if( envelopeInfoPtr->iSigCheckKeyset == CRYPT_ERROR )
				return( exitErrorNotInited( envelopeInfoPtr, 
											CRYPT_ENVINFO_KEYSET_SIGCHECK ) );

			/* Try and get the key.  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, NULL, 0,
							KEYMGMT_FLAG_NONE );
				}
			else
				{
				setMessageKeymgmtInfo( &getkeyInfo,
							CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
							contentListItem->issuerAndSerialNumber,
							contentListItem->issuerAndSerialNumberSize,
							NULL, 0, KEYMGMT_FLAG_NONE );
				}
			status = krnlSendMessage( envelopeInfoPtr->iSigCheckKeyset,
									  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
									  KEYMGMT_ITEM_PUBLICKEY );
			if( cryptStatusError( status ) )
				return( status );
			iCryptHandle = getkeyInfo.cryptHandle;

			/* Push the public key into the envelope, which performs the 
			   signature check.  Adding the key increments its reference 
			   count since the key is usually user-supplied and we need to 
			   keep a reference for use by the envelope, however since the 
			   key we're using here is an internal-use-only key we don't 
			   want to do this so we decrement it again after it's been 
			   added */
			*valuePtr = envelopeInfoPtr->addInfo( envelopeInfoPtr,
								CRYPT_ENVINFO_SIGNATURE, &iCryptHandle, TRUE );
			krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );

			/* If the key wasn't used for the sig check (i.e. it wasn't 
			   stored in the content list for later use, which means it isn't 
			   needed any more), discard it */
			if( sigInfo->iSigCheckKey == CRYPT_ERROR )
				krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
			return( CRYPT_OK );
			}

		case CRYPT_ENVINFO_SIGNATURE:
			{
			CONTENT_LIST *contentListItem = \
								envelopeInfoPtr->contentListCurrent;
			CONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;
			MESSAGE_CREATEOBJECT_INFO createInfo;
			RESOURCE_DATA msgData;
			BYTE certData[ 2048 ], *certDataPtr = certData;

			assert( contentListItem != NULL );

			/* If there's no signing key present, try and instantiate it 
			   from an attached cert chain */
			if( sigInfo->iSigCheckKey == CRYPT_ERROR )
				{
				if( envelopeInfoPtr->auxBuffer == NULL )
					/* There's no attached cert chain to recover the signing 
					   key from, we can't go any further */
					return( exitErrorNotFound( envelopeInfoPtr, 
											   CRYPT_ENVINFO_SIGNATURE ) );
				status = instantiateCertChain( envelopeInfoPtr, 
											   contentListItem );
				if( cryptStatusError( status ) )
					return( exitError( envelopeInfoPtr, 
									   CRYPT_ENVINFO_SIGNATURE, 
									   CRYPT_ERRTYPE_ATTR_VALUE, status ) );
				}

			/* If we instantiated the sig-check key ourselves (either from a 
			   keyset or from envelope data) rather than having it supplied
			   externally, we're done */
			if( !( contentListItem->flags & CONTENTLIST_EXTERNALKEY ) )
				{
				krnlSendNotifier( sigInfo->iSigCheckKey, 
								  IMESSAGE_INCREFCOUNT );
				*valuePtr = sigInfo->iSigCheckKey;
				return( CRYPT_OK );
				}

			/* The sig check key was externally supplied by the caller.  If 
			   they added a private key+cert combination as the sig.check 
			   key then this will return a supposed signature-check cert 
			   that actually has private-key capabilities.  Even adding a 
			   simple cert (+public key context for the sig.check) can be 
			   dangerous since it can act as a subliminal channel if it's 
			   passed on to a different user (although exactly how this would 
			   be exploitable is another question entirely).  To avoid this 
			   problem, we completely isolate the added sig.check key by 
			   exporting it and re-importing it as a new certificate object */
			setMessageData( &msgData, certDataPtr, 2048 );
			status = krnlSendMessage( sigInfo->iSigCheckKey,
									  IMESSAGE_CRT_EXPORT, &msgData,
									  CRYPT_CERTFORMAT_CERTCHAIN );
			if( status == CRYPT_ERROR_OVERFLOW )
				{
				if( ( certDataPtr = clAlloc( "processGetAttribute", \
											 msgData.length ) ) == NULL )
					return( CRYPT_ERROR_MEMORY );
				setMessageData( &msgData, certDataPtr, msgData.length );
				status = krnlSendMessage( sigInfo->iSigCheckKey,
										  IMESSAGE_CRT_EXPORT, &msgData,
										  CRYPT_CERTFORMAT_CERTCHAIN );
				}
			if( cryptStatusOK( status ) )
				{
				setMessageCreateObjectIndirectInfo( &createInfo, certDataPtr,
													msgData.length,
													CRYPT_CERTTYPE_CERTCHAIN );
				status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
										  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
										  &createInfo, OBJECT_TYPE_CERTIFICATE );
				}
			if( certDataPtr != certData )
				clFree( "processGetAttribute", certDataPtr );
			if( cryptStatusError( status ) )
				return( exitError( envelopeInfoPtr, 
								   CRYPT_ENVINFO_SIGNATURE, 
								   CRYPT_ERRTYPE_ATTR_VALUE, 
								   status ) );

			/* We've created a new instantiation of the sig.check key which 
			   is distinct from the externally-supplied original, return it 
			   to the caller */
			krnlSendNotifier( sigInfo->iSigCheckKey, IMESSAGE_DECREFCOUNT );
			*valuePtr = sigInfo->iSigCheckKey = createInfo.cryptHandle;
			return( CRYPT_OK );
			}

		case CRYPT_ENVINFO_SIGNATURE_EXTRADATA:
			{
			CRYPT_HANDLE iCryptHandle;
			CONTENT_LIST *contentListItem = \
								envelopeInfoPtr->contentListCurrent;

			assert( contentListItem != NULL );

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

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

#if 0	/* Unused, removed 9/9/03 */
		case CRYPT_IATTRIBUTE_PAYLOADSIZE:
			/* This is an internal attribute used by high-level cryptlib 
			   functions that use CMS as their native data format.  These
			   typically push the entire data quantity into an envelope
			   at once and then need to know how much data will be produced
			   to write to an output stream */
			*valuePtr = envelopeInfoPtr->bufPos;
			return( CRYPT_OK );
#endif /* 0 */

		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;
		}

	/* 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 );

⌨️ 快捷键说明

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