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

📄 envelope.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
				MESSAGE_CREATEOBJECT_INFO createInfo;

				setMessageCreateObjectInfo( &createInfo, 
											CRYPT_CERTTYPE_CMS_ATTRIBUTES );
				status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
										  RESOURCE_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, 
						RESOURCE_IMESSAGE_GETATTRIBUTE, &value, 
						CRYPT_CERTINFO_CMS_CONTENTTYPE ) != CRYPT_ERROR_NOTFOUND )
					krnlSendMessage( actionListPtr->iExtraData,
						RESOURCE_IMESSAGE_DELETEATTRIBUTE, NULL, 
						CRYPT_CERTINFO_CMS_CONTENTTYPE );
				krnlSendMessage( actionListPtr->iExtraData,
						RESOURCE_IMESSAGE_SETATTRIBUTE, &envelopeInfoPtr->contentType,
						CRYPT_CERTINFO_CMS_CONTENTTYPE );

				/* If it's an S/MIME (vs pure CMS) envelope, add the
				   sMIMECapabilities to further bloat things up */
				if( envelopeInfoPtr->type == CRYPT_FORMAT_SMIME )
					{
					krnlSendMessage( actionListPtr->iExtraData,
									 RESOURCE_IMESSAGE_SETATTRIBUTE, 
									 MESSAGE_VALUE_UNUSED,
									 CRYPT_CERTINFO_CMS_SMIMECAP_3DES );
					if( algoAvailable( CRYPT_ALGO_AES ) )
						krnlSendMessage( actionListPtr->iExtraData,
										 RESOURCE_IMESSAGE_SETATTRIBUTE, 
										 MESSAGE_VALUE_UNUSED,
										 CRYPT_CERTINFO_CMS_SMIMECAP_AES );
					if( algoAvailable( CRYPT_ALGO_CAST ) )
						krnlSendMessage( actionListPtr->iExtraData,
										 RESOURCE_IMESSAGE_SETATTRIBUTE, 
										 MESSAGE_VALUE_UNUSED,
										 CRYPT_CERTINFO_CMS_SMIMECAP_CAST128 );
					if( algoAvailable( CRYPT_ALGO_IDEA ) )
						krnlSendMessage( actionListPtr->iExtraData,
										 RESOURCE_IMESSAGE_SETATTRIBUTE, 
										 MESSAGE_VALUE_UNUSED,
										 CRYPT_CERTINFO_CMS_SMIMECAP_IDEA );
					if( algoAvailable( CRYPT_ALGO_RC2 ) )
						krnlSendMessage( actionListPtr->iExtraData,
										 RESOURCE_IMESSAGE_SETATTRIBUTE, 
										 MESSAGE_VALUE_UNUSED,
										 CRYPT_CERTINFO_CMS_SMIMECAP_RC2 );
					if( algoAvailable( CRYPT_ALGO_SKIPJACK ) )
						krnlSendMessage( actionListPtr->iExtraData,
										 RESOURCE_IMESSAGE_SETATTRIBUTE, 
										 MESSAGE_VALUE_UNUSED,
										 CRYPT_CERTINFO_CMS_SMIMECAP_SKIPJACK );
					}
				}
			}

		/* Determine the type of signing attributes to use.  If none are 
		   specified (which can only happen if the signed content is data),
		   either get the signing code to add the default ones for use, or
		   use none at all if the use of default attributes is disabled */
		signingAttributes = actionListPtr->iExtraData;
		if( signingAttributes == CRYPT_ERROR )
			{
			int useDefaultAttributes;

			krnlSendMessage( envelopeInfoPtr->ownerHandle, 
							 RESOURCE_IMESSAGE_GETATTRIBUTE, 
							 &useDefaultAttributes, 
							 CRYPT_OPTION_CMS_DEFAULTATTRIBUTES );
			signingAttributes = useDefaultAttributes ? \
								CRYPT_USE_DEFAULT : CRYPT_UNUSED;
			}

		/* Evaluate the size of the exported action.  Even though it's not
		   required for encoding the length for DLP-based PKC's, we still 
		   need to evaluate it to check that everything will be OK later on
		   and to determine whether the allocated auxBuffer is big enough to 
		   contain the largest possible signature */
		status = iCryptCreateSignatureEx( NULL, &signatureSize,
						envelopeInfoPtr->type, actionListPtr->iCryptHandle,
						actionListPtr->associatedAction->iCryptHandle,
						signingAttributes, 
						( actionListPtr->iTspSession != CRYPT_ERROR ) ? \
						actionListPtr->iTspSession : CRYPT_UNUSED );
		if( cryptStatusError( status ) )
			return( status );
		status = krnlSendMessage( actionListPtr->iCryptHandle, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE, &cryptAlgo,
								  CRYPT_CTXINFO_ALGO );
		if( cryptStatusError( status ) )
			return( status );
		if( cryptAlgo == CRYPT_ALGO_DSA || \
			actionListPtr->iTspSession != CRYPT_ERROR )
			{
			/* If there are any signature actions which will result in
			   indefinite-length encodings present, we can't use a definite-
			   length encoding for the signatures */
			envelopeInfoPtr->hasIndefiniteTrailer = TRUE;
			actionListPtr->encodedSize = CRYPT_UNUSED;
			}
		else
			{
			actionListPtr->encodedSize = signatureSize;
			envelopeInfoPtr->signActionSize += signatureSize;
			}
		if( signatureSize > largestSignatureSize )
			largestSignatureSize = signatureSize;
		}
	largestSignatureSize += 64;		/* Add some slop for ASN.1 wrappers */

	/* If we're signing with very long cert chains or chains where the certs
	   have half the Verisign CPS included as text, the auxBuffer may not be
	   large enough to contain the resulting signature, so we have to expand
	   it to handle the signature */
	if( envelopeInfoPtr->auxBufSize < largestSignatureSize )
		{
		if( envelopeInfoPtr->auxBuffer != NULL )
			free( envelopeInfoPtr->auxBuffer );
		if( ( envelopeInfoPtr->auxBuffer = malloc( largestSignatureSize ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		envelopeInfoPtr->auxBufSize = largestSignatureSize;
		}

	/* Hashing is now active */
	envelopeInfoPtr->hashActionsActive = TRUE;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Emit Header Functions						*
*																			*
****************************************************************************/

/* Write the header fields which encapsulate any enveloped data:

   SignedData/DigestedData */

static int writeAuthenticatedDataHeader( STREAM *stream,
										 const ENVELOPE_INFO *envelopeInfoPtr,
										 const BOOLEAN isSignedData )
	{
	const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
	ACTION_LIST *actionListPtr;
	long dataSize;
	int hashActionSize = 0;

	/* Determine the size of the hash actions */
	for( actionListPtr = envelopeInfoPtr->actionList; actionListPtr != NULL; 
		 actionListPtr = actionListPtr->next )
		hashActionSize += sizeofContextAlgoID( actionListPtr->iCryptHandle,
											   CRYPT_ALGO_NONE, 
											   ALGOID_FLAG_ALGOID_ONLY );

	/* Determine the size of the SignedData/DigestedData */
	if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \
		envelopeInfoPtr->hasIndefiniteTrailer )
		dataSize = CRYPT_UNUSED;
	else
		{
		/* Determine the size of the content OID + content */
		dataSize = ( envelopeInfoPtr->payloadSize ) ? \
			sizeofObject( sizeofObject( envelopeInfoPtr->payloadSize ) ) : 0;
		dataSize = sizeofObject( sizeofOID( contentOID ) + dataSize );

		/* Determine the size of the version, hash algoID, content, cert
		   chain, and signatures */
		dataSize = sizeofShortInteger( 1 ) + sizeofObject( hashActionSize ) + \
				   dataSize + envelopeInfoPtr->extraDataSize + \
				   sizeofObject( envelopeInfoPtr->signActionSize );
		}

	/* Write the SignedData/DigestedData header, version number, and SET OF
	   DigestInfo */
	writeCMSheader( stream, ( isSignedData ) ? \
					OID_CMS_SIGNEDDATA : OID_CMS_DIGESTEDDATA, dataSize, 
					FALSE );
	writeShortInteger( stream, 1, DEFAULT_TAG );
	writeSet( stream, hashActionSize );
	for( actionListPtr = envelopeInfoPtr->actionList; actionListPtr != NULL;
		 actionListPtr = actionListPtr->next )
		{
		int status = writeContextAlgoID( stream,
							actionListPtr->iCryptHandle, CRYPT_ALGO_NONE,
							ALGOID_FLAG_ALGOID_ONLY );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Write the inner Data header */
	return( writeCMSheader( stream, contentOID, envelopeInfoPtr->payloadSize, 
							TRUE ) );
	}

/* EncryptedContentInfo contained within EnvelopedData */

static int writeEncryptedContentHeader( STREAM *stream,
							const BYTE *contentOID,
							const CRYPT_CONTEXT iCryptContext,
							const long payloadSize, const long blockSize )
	{
	const long blockedPayloadSize = ( payloadSize == CRYPT_UNUSED ) ? \
						CRYPT_UNUSED : paddedSize( payloadSize, blockSize );

	return( writeCMSencrHeader( stream, contentOID, blockedPayloadSize,
								iCryptContext ) );
	}

/* EncryptedData, EnvelopedData */

static void writeEncryptionHeader( STREAM *stream, const BYTE *oid,
								   const int version, const long payloadSize,
								   const long blockSize, const long extraSize )
	{
	const long blockedPayloadSize = ( payloadSize == CRYPT_UNUSED ) ? \
						CRYPT_UNUSED : paddedSize( payloadSize, blockSize );

	writeCMSheader( stream, oid, 
					( payloadSize == CRYPT_UNUSED || extraSize == CRYPT_UNUSED ) ? \
						CRYPT_UNUSED : \
						sizeofShortInteger( 0 ) + extraSize + blockedPayloadSize,
					FALSE );
	writeShortInteger( stream, version, DEFAULT_TAG );
	}

static int writeEncryptedDataHeader( STREAM *stream,
									 const ENVELOPE_INFO *envelopeInfoPtr )
	{
	const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
	const int encrContentInfoSize = sizeofCMSencrHeader( contentOID,
			envelopeInfoPtr->payloadSize, envelopeInfoPtr->iCryptContext );

	if( cryptStatusError( encrContentInfoSize ) )
		return( encrContentInfoSize );

	/* Write the EncryptedData header and version number, and
	   EncryptedContentInfo header */
	writeEncryptionHeader( stream, OID_CMS_ENCRYPTEDDATA, 0,
				envelopeInfoPtr->payloadSize, envelopeInfoPtr->blockSize,
				encrContentInfoSize );
	return( writeEncryptedContentHeader( stream, contentOID,
				envelopeInfoPtr->iCryptContext, envelopeInfoPtr->payloadSize,
				envelopeInfoPtr->blockSize ) );
	}

static int writeEnvelopedDataHeader( STREAM *stream,
									 const ENVELOPE_INFO *envelopeInfoPtr )
	{
	const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
	const int encrContentInfoSize = sizeofCMSencrHeader( contentOID,
			envelopeInfoPtr->payloadSize, envelopeInfoPtr->iCryptContext );
	const int originatorInfoSize = envelopeInfoPtr->extraDataSize ? \
			( int ) sizeofObject( envelopeInfoPtr->extraDataSize ) : 0;

	if( cryptStatusError( encrContentInfoSize ) )
		return( encrContentInfoSize );

	/* Write the EnvelopedData header and version number and start of the SET
	   OF RecipientInfo/EncryptionKeyInfo */
	writeEncryptionHeader( stream, OID_CMS_ENVELOPEDDATA, 
				originatorInfoSize ? 2 : 0, envelopeInfoPtr->payloadSize, 
				envelopeInfoPtr->blockSize, 
				( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
					CRYPT_UNUSED : \
					sizeofObject( envelopeInfoPtr->cryptActionSize ) +
					originatorInfoSize + encrContentInfoSize ) );
	if( originatorInfoSize )
		{
		RESOURCE_DATA msgData;
		int status;

		/* Write the wrapper for the originator info and the originator info 
		   itself */
		writeCtag( stream, 0 );
		writeLength( stream, envelopeInfoPtr->extraDataSize );

		/* Export the originator cert chain either directly into the main 
		   buffer or into the auxBuffer if there's not enough room */
		if( originatorInfoSize >= sMemDataLeft( stream ) )
			{
			/* The originator chain is too big for the main buffer, we have
			   to write everything from this point on into the auxBuffer.  
			   This is then flushed into the main buffer in the calling code 
			   before anything else is written */
			stream = ( STREAM * ) &envelopeInfoPtr->auxStream;
			setResourceData( &msgData, envelopeInfoPtr->auxBuffer, 
							 envelopeInfoPtr->auxBufSize );
			}
		else
			setResourceData( &msgData, sMemBufPtr( stream ), 
							 sMemDataLeft( stream ) );
		status = krnlSendMessage( envelopeInfoPtr->iOriginatorChain,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_CERTSET );
		if( cryptStatusError( status ) )
			return( status );
		sSkip( stream, msgData.length );
		}

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

/* CompressedData */

static void 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 */
	writeCMSheader( stream, getContentOID( envelopeInfoPtr->contentType ), 
					CRYPT_UNUSED, TRUE );
	}

/****************************************************************************
*																			*
*							Emit Envelope Preamble/Postamble				*
*																			*
****************************************************************************/

/* Output as much of the preamble as possible into the envelope buffer */

static int emitPreamble( ENVELOPE_INFO *envelopeInfoPtr )
	{
	ENV_STATE state = envelopeInfoPtr->envState;
	int status = CRYPT_OK;

	/* If there's any data left in the auxiliary buffer, try and empty that
	   first */
	if( envelopeInfoPtr->auxBufPos && copyFromAuxBuffer( envelopeInfoPtr ) )
		return( CRYPT_ERROR_OVERFLOW );

	/* If we've finished processing the header information, don't do
	   anything */
	if( state == ENVSTATE_DONE )
		return( CRYPT_OK );

	/* If we haven't started doing anything yet, perform various final
	   initialisations */
	if( state == ENVSTATE_NONE )
		{
		/* If there's no nested content type set, default to plain data */
		if( envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )
			envelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;

		/* Perform any remaining initialisation.  MAC'd data is a special-
		   case form of encrypted data so we treat them as the same thing
		   at the key exchange level */
		if( envelopeInfoPtr->usage == ACTION_CRYPT || \
			envelopeInfoPtr->usage == ACTION_MAC )
			status = preEnvelopeEncrypt( envelopeInfoPtr );
		else
			if( envelopeInfoPtr->usage == ACTION_SIGN )
				status = preEnvelopeSign( envelopeInfoPtr );
		if( cryptStatusError( status ) )
			return( status );

		/* Delete any orphaned actions (for example automatically added
		   hash actions which were overridden with user-supplied alternate
		   actions) */
		deleteUnusedActions( envelopeInfoPtr );

		/* We're ready to go, connect a write stream to the auxBuffer and
		   prepare to emit the outer header */
		sMemOpen( &envelopeInfoPtr->auxStream, envelopeInfoPtr->auxBuffer,
				  envelopeInfoPtr->auxBufSize );
		state = ENVSTATE_HEADER;
		assert( actionsOK( envelopeInfoPtr ) );
		}

	/* Emit the outer header */
	if( state == ENVSTATE_HEADER )
		{
		STREAM stream;

		/* If we're encrypting, set up the encryption-related information */
		if( envelopeInfoPtr->usage == ACTION_CRYPT )

⌨️ 快捷键说明

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