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

📄 env_cms.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Write the AuthenticatedData header and version number and start of the SET
	   OF RecipientInfo */
	if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
		writeEncryptionHeader( stream, OID_CMS_AUTHDATA, 0, CRYPT_UNUSED, 1, 
							   CRYPT_UNUSED );
	else
		{
		int dataSize;

		dataSize = ( envelopeInfoPtr->payloadSize ) ? \
			sizeofObject( sizeofObject( envelopeInfoPtr->payloadSize ) ) : 0;
		dataSize = sizeofObject( sizeofOID( contentOID ) + dataSize );

		writeEncryptionHeader( stream, OID_CMS_AUTHDATA, 0, 
				envelopeInfoPtr->payloadSize, 1, 
				( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
					CRYPT_UNUSED : \
					sizeofObject( envelopeInfoPtr->cryptActionSize ) +
					macActionSize + dataSize );
		}

	return( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
			writeSetIndef( stream ) : \
			writeSet( stream, envelopeInfoPtr->cryptActionSize ) );
	}

/* CompressedData */

static int writeCompressedDataHeader( STREAM *stream,
									  ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Since compressing the data changes its length, we have to use the
	   indefinite-length encoding even if we know how big the payload is */
	envelopeInfoPtr->payloadSize = CRYPT_UNUSED;

	/* Write the CompressedData header, version number, and Zlib algoID */
	writeCMSheader( stream, OID_CMS_COMPRESSEDDATA, CRYPT_UNUSED, FALSE );
	writeShortInteger( stream, 0, DEFAULT_TAG );
	swrite( stream, ALGOID_CMS_ZLIB, sizeofOID( ALGOID_CMS_ZLIB ) );

	/* Write the inner Data header */
	return( writeCMSheader( stream, getContentOID( envelopeInfoPtr->contentType ), 
							CRYPT_UNUSED, TRUE ) );
	}

/****************************************************************************
*																			*
*						Content-Specific Pre-processing						*
*																			*
****************************************************************************/

/* Pre-process information for encrypted enveloping */

static int processKeyexchangeAction( ENVELOPE_INFO *envelopeInfoPtr,
									 ACTION_LIST *actionListPtr,
									 const CRYPT_DEVICE iCryptDevice )
	{
	int cryptAlgo, status;
#ifdef USE_KEA
	BYTE originatorDomainParams[ CRYPT_MAX_HASHSIZE ];
	int originatorDomainParamSize = 0;
#endif /* USE_KEA */

	assert( actionListPtr->action == ACTION_KEYEXCHANGE_PKC || \
			actionListPtr->action == ACTION_KEYEXCHANGE );

	/* If the session key/MAC context is tied to a device, make sure that 
	   the key exchange object is in the same device */
	if( iCryptDevice != CRYPT_ERROR )
		{
		CRYPT_DEVICE iKeyexDevice;

		status = krnlSendMessage( actionListPtr->iCryptHandle, 
								  MESSAGE_GETDEPENDENT, &iKeyexDevice, 
								  OBJECT_TYPE_DEVICE );
		if( cryptStatusError( status ) || iCryptDevice != iKeyexDevice )
			return( CRYPT_ERROR_INVALID );
		}

#ifdef USE_KEA
	/* If there's an originator chain present, get the originator's domain 
	   parameters and if the key is tied to a device, get the device's handle
	   so that we can create the session key object in it */
	if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, originatorDomainParams, 
						 CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,
								  IMESSAGE_GETATTRIBUTE_S, &msgData, 
								  CRYPT_IATTRIBUTE_KEY_KEADOMAINPARAMS );
		if( cryptStatusError( status ) )
			return( status );
		originatorDomainParamSize = msgData.length;
		status = krnlSendMessage( envelopeInfoPtr->iExtraCertChain, 
								  IMESSAGE_GETDEPENDENT, &iCryptDevice,
								  OBJECT_TYPE_DEVICE );
		if( cryptStatusError( status ) )
			iCryptDevice = CRYPT_ERROR;
		}

	/* If it's a key agreement action, make sure that there's originator 
	   info present and that the domain parameters match */
	if( actionListPtr->action == ACTION_KEYEXCHANGE_PKC && \
		cryptStatusOK( krnlSendMessage( actionListPtr->iCryptHandle, 
										IMESSAGE_CHECK, NULL, 
										MESSAGE_CHECK_PKC_KA_EXPORT ) ) )
		{
		RESOURCE_DATA msgData;
		BYTE domainParams[ CRYPT_MAX_HASHSIZE ];

		if( !originatorDomainParamSize )
			{
			setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_ORIGINATOR,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}
		setMessageData( &msgData, domainParams, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( actionListPtr->iCryptHandle,
								  IMESSAGE_GETATTRIBUTE_S, &msgData, 
								  CRYPT_IATTRIBUTE_KEY_DOMAINPARAMS );
		if( cryptStatusError( status ) )
			return( status );
		if( ( originatorDomainParamSize != msgData.length ) || \
			memcmp( originatorDomainParams, domainParams, 
					originatorDomainParamSize ) )
			{
			setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_ORIGINATOR,
						  CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}
#endif /* USE_KEA */

	/* Remember that we now have a controlling action and connect the 
	   controller to the subject */
	envelopeInfoPtr->actionList->flags &= ~ACTION_NEEDSCONTROLLER;
	actionListPtr->associatedAction = envelopeInfoPtr->actionList;

	/* Evaluate the size of the exported action.  If it's a conventional key 
	   exchange, we force the use of the CMS format since there's no reason 
	   to use the cryptlib format */
	status = iCryptExportKeyEx( NULL, &actionListPtr->encodedSize, 0,
						( actionListPtr->action == ACTION_KEYEXCHANGE ) ? \
							CRYPT_FORMAT_CMS : envelopeInfoPtr->type,
						envelopeInfoPtr->actionList->iCryptHandle,
						actionListPtr->iCryptHandle, 
						( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR ) ? \
							envelopeInfoPtr->iExtraCertChain : CRYPT_UNUSED );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( actionListPtr->iCryptHandle, 
								  IMESSAGE_GETATTRIBUTE, &cryptAlgo, 
								  CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );

	/* If there are any key exchange actions that will result in indefinite-
	   length encodings present, we can't use a definite-length encoding for 
	   the key exchange actions */
	return( ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? OK_SPECIAL : CRYPT_OK );
	}

static int preEnvelopeEncrypt( ENVELOPE_INFO *envelopeInfoPtr )
	{
	CRYPT_DEVICE iCryptDevice = CRYPT_ERROR;
	ACTION_LIST *actionListPtr;
	BOOLEAN hasIndefSizeActions = FALSE;
	int totalSize, status;

#ifdef USE_KEA
	/* If there's originator info present, find out what it'll take to encode
	   it into the envelope header */
	if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
		{
		RESOURCE_DATA msgData;
		int status;

		/* Determine how big the originator cert chain will be */
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,
								  IMESSAGE_CRT_EXPORT, &msgData,
								  CRYPT_ICERTFORMAT_CERTSET );
		if( cryptStatusError( status ) )
			return( status );
		envelopeInfoPtr->extraDataSize = msgData.length;

		/* If we have very long originator cert chains the auxBuffer may not 
		   be large enough to contain the resulting chain, so we have to 
		   expand it to handle the chain */
		if( envelopeInfoPtr->auxBufSize < envelopeInfoPtr->extraDataSize + 64 )
			{
			if( ( envelopeInfoPtr->auxBuffer = \
					clDynAlloc( "preEnvelopeEncrypt", \
								envelopeInfoPtr->extraDataSize + 64 ) ) == NULL )
				return( CRYPT_ERROR_MEMORY );
			envelopeInfoPtr->auxBufSize = envelopeInfoPtr->extraDataSize + 64;
			}
		}
#endif /* USE_KEA */

	/* If there are no key exchange actions present, we're done */
	if( envelopeInfoPtr->preActionList == NULL )
		return( CRYPT_OK );

	/* Create the session/MAC key if necessary */
	if( envelopeInfoPtr->actionList == NULL )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		/* Create a default encryption action and add it to the action
		   list */
		setMessageCreateObjectInfo( &createInfo, 
							( envelopeInfoPtr->usage == ACTION_CRYPT ) ? \
								envelopeInfoPtr->defaultAlgo : \
								envelopeInfoPtr->defaultMAC );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusOK( status ) )
			{
			status = krnlSendMessage( createInfo.cryptHandle, 
									  IMESSAGE_CTX_GENKEY, NULL, FALSE );
			if( cryptStatusOK( status ) && \
				addAction( &envelopeInfoPtr->actionList,
						   envelopeInfoPtr->memPoolState, 
						   envelopeInfoPtr->usage, 
						   createInfo.cryptHandle ) == NULL )
				status = CRYPT_ERROR_MEMORY;
			if( cryptStatusError( status ) )
				krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			}
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		{
		/* If the session key/MAC context is tied to a device, get its handle 
		   so we can check that all key exchange objects are also in the same 
		   device */
		status = krnlSendMessage( envelopeInfoPtr->actionList->iCryptHandle, 
								  MESSAGE_GETDEPENDENT, &iCryptDevice, 
								  OBJECT_TYPE_DEVICE );
		if( cryptStatusError( status ) )
			iCryptDevice = CRYPT_ERROR;
		}

	/* Notify the kernel that the session key/MAC context is attached to the 
	   envelope.  This is an internal object used only by the envelope, so 
	   we tell the kernel not to increment its reference count when it 
	   attaches it */
	krnlSendMessage( envelopeInfoPtr->objectHandle, IMESSAGE_SETDEPENDENT, 
					 &envelopeInfoPtr->actionList->iCryptHandle, 
					 SETDEP_OPTION_NOINCREF );

	/* Now walk down the list of key exchange actions evaluating their size 
	   and connecting each one to the session key action */
	totalSize = 0;
	for( actionListPtr = envelopeInfoPtr->preActionList;
		 actionListPtr != NULL; actionListPtr = actionListPtr->next )
		{
		status = processKeyexchangeAction( envelopeInfoPtr, actionListPtr, 
										   iCryptDevice );
		if( cryptStatusError( status ) )
			{
			if( status != OK_SPECIAL )
				return( status );
			hasIndefSizeActions = TRUE;
			}
		totalSize += actionListPtr->encodedSize;
		}
	envelopeInfoPtr->cryptActionSize = hasIndefSizeActions ? \
									   CRYPT_UNUSED : totalSize;
	return( CRYPT_OK );
	}

/* Pre-process information for signed enveloping */

static int processSignatureAction( ENVELOPE_INFO *envelopeInfoPtr, 
								   ACTION_LIST *actionListPtr )
	{
	int cryptAlgo, signatureSize, signingAttributes, status;

	assert( actionListPtr->action == ACTION_SIGN );

	/* Process signing certs if necessary and match the content-type in the 
	   authenticated attributes with the signed content type if it's anything 
	   other than 'data' (the data content-type is added automatically) */
	if( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \
		envelopeInfoPtr->type == CRYPT_FORMAT_SMIME )
		{
		/* If we're including signing certs and there are multiple signing 
		   certs present, add the currently-selected one to the overall cert 
		   collection */
		if( !( envelopeInfoPtr->flags & ENVELOPE_NOSIGNINGCERTS ) && \
			envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
			{
			status = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,
									  IMESSAGE_SETATTRIBUTE,
									  &actionListPtr->iCryptHandle,
									  CRYPT_IATTRIBUTE_CERTCOLLECTION );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* If there's no content-type present and the signed content type 
		   isn't 'data' or it's an S/MIME envelope, create signing attributes 
		   to hold the content-type and smimeCapabilities.  Then, make sure 
		   that the content-type in the attributes matches the actual content 
		   type */
		if( actionListPtr->iExtraData == CRYPT_ERROR && \
			( envelopeInfoPtr->contentType != CRYPT_CONTENT_DATA || \
			  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) )
			{
			MESSAGE_CREATEOBJECT_INFO createInfo;

			setMessageCreateObjectInfo( &createInfo, 
										CRYPT_CERTTYPE_CMS_ATTRIBUTES );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
									  IMESSAGE_DEV_CREATEOBJECT,
									  &createInfo, OBJECT_TYPE_CERTIFICATE );
			if( cryptStatusError( status ) )
				return( status );
			actionListPtr->iExtraData = createInfo.cryptHandle;
			}
		if( actionListPtr->iExtraData != CRYPT_ERROR )
			{
			int value;

			/* Delete any existing content-type (quietly fixing things if
			   necessary is easier than trying to report this error back to 
			   the caller) and add our one */
			if( krnlSendMessage( actionListPtr->iExtraData, 
						IMESSAGE_GETATTRIBUTE, &value, 
						CRYPT_CERTINFO_CMS_CONTENTTYPE ) != CRYPT_ERROR_NOTFOUND )
				krnlSendMessage( actionListPtr->iExtraData,
								 IMESSAGE_DELETEATTRIBUTE, NULL, 

⌨️ 快捷键说明

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