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

📄 envelope.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
			{
			status = initEnvelopeEncryption( envelopeInfoPtr,
								envelopeInfoPtr->actionList->iCryptHandle, 
								CRYPT_UNUSED, CRYPT_UNUSED, NULL, 0, FALSE );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* Write the appropriate CMS header based on the envelope usage.
		   Since this is the first data written, we can write it directly to
		   the envelope buffer without having to go via the auxBuffer.  The
		   DigestedData action is never taken since the higher-level code
		   assumes that the presence of hash actions indicates the desire to
		   create signed data and returns an error if no signature actions
		   are present */
		sMemOpen( &stream, envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );
		switch( envelopeInfoPtr->usage )
			{
			case ACTION_CRYPT:
				if( envelopeInfoPtr->preActionList == NULL )
					status = writeEncryptedDataHeader( &stream, envelopeInfoPtr );
				else
					status = writeEnvelopedDataHeader( &stream, envelopeInfoPtr );
				break;

			case ACTION_SIGN:
				status = writeAuthenticatedDataHeader( &stream, 
												envelopeInfoPtr, TRUE );
				break;

			case ACTION_HASH:
				status = writeAuthenticatedDataHeader( &stream, 
												envelopeInfoPtr, FALSE );
				break;

			case ACTION_COMPRESS:
				writeCompressedDataHeader( &stream, envelopeInfoPtr );
				break;

			case ACTION_NONE:
				writeCMSheader( &stream, OID_CMS_DATA, 
								envelopeInfoPtr->payloadSize, FALSE );
				break;

			default:
				assert( NOTREACHED );
			}
		envelopeInfoPtr->bufPos = ( int ) stell( &stream );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			return( status );

		/* If we're not encrypting with key exchange actions, we're done */
		if( envelopeInfoPtr->usage != ACTION_CRYPT || \
			envelopeInfoPtr->preActionList == NULL )
			{
			/* Make sure we start a new segment if we try to add any data,
			   set the block size mask to all ones if we're not encrypting
			   (since we can begin and end data segments on arbitrary
			   boundaries), and record the fact that we're done */
			envelopeInfoPtr->segmentComplete = TRUE;
			if( envelopeInfoPtr->usage != ACTION_CRYPT )
				envelopeInfoPtr->blockSizeMask = -1;
			envelopeInfoPtr->lastAction = NULL;
			envelopeInfoPtr->envState = ENVSTATE_DONE;
			return( CRYPT_OK );
			}

		/* Start emitting the key exchange actions */
		envelopeInfoPtr->lastAction = findAction( envelopeInfoPtr->preActionList,
												  ACTION_KEYEXCHANGE_PKC );
		if( envelopeInfoPtr->lastAction == NULL )
			envelopeInfoPtr->lastAction = findAction( envelopeInfoPtr->preActionList,
													  ACTION_KEYEXCHANGE );
		state = ENVSTATE_KEYINFO;

		/* In very rare instances (when we're using a key agreement key and 
		   there's a lot of originator info) the header can contain a large 
		   amount of data which won't fit into the main buffer, so we copy it 
		   into the auxBuffer instead.  If this happens we need to tell the 
		   user to pop some data so we can move more of it out of the 
		   auxBuffer */
		if( envelopeInfoPtr->auxBufPos && copyFromAuxBuffer( envelopeInfoPtr ) )
			{
			envelopeInfoPtr->envState = ENVSTATE_KEYINFO;
			return( CRYPT_ERROR_OVERFLOW );
			}
		}

	/* Keep producing output until we fill the envelope buffer or run out of
	   header information to encode */
	while( state != ENVSTATE_DONE )
		{
		/* Handle key export actions */
		if( state == ENVSTATE_KEYINFO )
			{
			ACTION_LIST *lastActionPtr = envelopeInfoPtr->lastAction;

			/* Export the session key using each of the PKC or conventional
			   keys.  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 */
			while( cryptStatusOK( status ) && lastActionPtr != NULL )
				{
				status = iCryptExportKeyEx( envelopeInfoPtr->auxBuffer,
							&envelopeInfoPtr->auxBufPos, 
							( lastActionPtr->action == ACTION_KEYEXCHANGE ) ? \
							CRYPT_FORMAT_CMS : envelopeInfoPtr->type,
							envelopeInfoPtr->iCryptContext,
							lastActionPtr->iCryptHandle,
							( envelopeInfoPtr->iOriginatorChain != CRYPT_ERROR ) ? \
								envelopeInfoPtr->iOriginatorChain : CRYPT_UNUSED );
				if( !cryptStatusError( status ) )
					{
					lastActionPtr = lastActionPtr->next;
					if( copyFromAuxBuffer( envelopeInfoPtr ) )
						status = CRYPT_ERROR_OVERFLOW;
					}
				}
			envelopeInfoPtr->lastAction = lastActionPtr;

			/* If we've reached the last key exchange action, move on to the
			   next state.  Since the emission of the key exchange
			   information is interruptible, we only move on to the next
			   state if there are no errors */
			if( cryptStatusError( status ) )
				break;
			if( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED )
				/* If it's an indefinite-length header, close off the set of
				   key exchange actions */
				writeEndIndef( &envelopeInfoPtr->auxStream );
			state = ENVSTATE_ENCRINFO;
			}

		/* Handle encrypted content information */
		if( state == ENVSTATE_ENCRINFO )
			{
			/* Write the encrypted content header */
			status = writeEncryptedContentHeader( &envelopeInfoPtr->auxStream,
				getContentOID( envelopeInfoPtr->contentType ),
				envelopeInfoPtr->iCryptContext, envelopeInfoPtr->payloadSize,
				envelopeInfoPtr->blockSize );
			if( cryptStatusOK( status ) && \
				copyFromAuxStream( envelopeInfoPtr ) )
				status = CRYPT_ERROR_OVERFLOW;

			/* Make sure we start a new segment if we try to add any data */
			envelopeInfoPtr->segmentComplete = TRUE;

			/* We're done */
			state = ENVSTATE_DONE;
			}
		}

	/* Remember the state information */
	envelopeInfoPtr->envState = state;

	return( status );
	}

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

static int emitPostamble( 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 );

	/* Emit the trailer */
	if( state == ENVSTATE_NONE )
		{
		/* Finish the OCTET STRING encoding by flushing any remaining data
		   from internal buffers into the envelope buffer and adding PKCS #5
		   padding if we're using a block encryption mode */
		status = envelopeInfoPtr->copyToEnvelope( envelopeInfoPtr, 
												  ( BYTE * ) "", 0 );
		if( cryptStatusError( status ) )
			return( status );

		/* If it's something other than pure encrypted data, emit the data
		   end-of-contents octets and follow it with the trailer */
		if( envelopeInfoPtr->usage == ACTION_SIGN )
			{
			/* Write the end-of-contents octets for the Data OCTET STRING,
			   [0], and SEQUENCE if necessary */
			if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
				{
				writeEndIndef( &envelopeInfoPtr->auxStream );
				writeEndIndef( &envelopeInfoPtr->auxStream );
				writeEndIndef( &envelopeInfoPtr->auxStream );
				}
			envelopeInfoPtr->lastAction = envelopeInfoPtr->postActionList;

			/* Write the signing cert chain if it's a CMS signature and 
			   they're not explicitly excluded, followed by the SET OF 
			   SignerInfo header */
			if( ( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \
				  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) && \
				!( envelopeInfoPtr->flags & ENVELOPE_NOSIGNINGCERTS ) )
				{
				RESOURCE_DATA msgData;

				setResourceData( &msgData, 
								 sMemBufPtr( &envelopeInfoPtr->auxStream ), 
								 sMemDataLeft( &envelopeInfoPtr->auxStream ) );
				status = krnlSendMessage( envelopeInfoPtr->lastAction->iCryptHandle,
								RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								CRYPT_IATTRIBUTE_CERTSET );
				if( cryptStatusError( status ) )
					return( status );
				sSkip( &envelopeInfoPtr->auxStream,
					   envelopeInfoPtr->extraDataSize );
				}
			if( envelopeInfoPtr->hasIndefiniteTrailer )
				writeSetIndef( &envelopeInfoPtr->auxStream );
			else
				writeSet( &envelopeInfoPtr->auxStream,
						  envelopeInfoPtr->signActionSize );

			state = ENVSTATE_SIGNATURE;
			if( copyFromAuxStream( envelopeInfoPtr ) )
				{
				envelopeInfoPtr->envState = state;
				return( CRYPT_ERROR_OVERFLOW );
				}
			}
		else
			{
			/* There's no trailer, emit the various end-of-contents octets if 
			   necessary */
			if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) 
				{
				/* Write the end-of-contents octets for the encapsulated data
				   if necessary */
				if( envelopeInfoPtr->usage == ACTION_CRYPT || \
					envelopeInfoPtr->usage == ACTION_COMPRESS ) 
					{
					writeEndIndef( &envelopeInfoPtr->auxStream );
					writeEndIndef( &envelopeInfoPtr->auxStream );
					if( envelopeInfoPtr->usage == ACTION_COMPRESS )
						/* Compressed data requires an extra EOC due to the 
						   explicit tagging */
						writeEndIndef( &envelopeInfoPtr->auxStream );
					}
				state = ENVSTATE_EOC;
				}
			else
				state = ENVSTATE_DONE;
			}
		}

	/* Keep producing output until we fill the envelope buffer or run out of
	   trailer information to encode */
	while( state != ENVSTATE_DONE )
		{
		/* Handle signing actions */
		if( state == ENVSTATE_SIGNATURE )
			{
			ACTION_LIST *lastActionPtr = envelopeInfoPtr->lastAction;

			assert( lastActionPtr != NULL && lastActionPtr->action == ACTION_SIGN );

			/* Sign each hash using the associated signature key */
			while( cryptStatusOK( status ) && lastActionPtr != NULL )
				{
				int signingAttributes;

				/* Determine the type of signing attributes to use.  If none 
				   are specified (which can only happen under circumstances
				   controlled by the pre-envelope-signing code), 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 = lastActionPtr->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;
					}

				/* Generate the signature into the aux.buffer and copy as
				   much as possible of it into the envelope buffer */
				status = iCryptCreateSignatureEx( envelopeInfoPtr->auxBuffer,
						&envelopeInfoPtr->auxBufPos, envelopeInfoPtr->type,
						lastActionPtr->iCryptHandle,
						lastActionPtr->associatedAction->iCryptHandle,
						signingAttributes, 
						( lastActionPtr->iTspSession != CRYPT_ERROR ) ? \
						lastActionPtr->iTspSession : CRYPT_UNUSED );
				lastActionPtr = lastActionPtr->next;
				if( !cryptStatusError( status ) && \
					copyFromAuxBuffer( envelopeInfoPtr ) )
					status = CRYPT_ERROR_OVERFLOW;
				}
			envelopeInfoPtr->lastAction = lastActionPtr;

			/* If we've reached the last signature action, move on to the
			   next state.  Since the emission of the signature information
			   is interruptible, we only move on to the next state if there
			   are no errors */
			if( cryptStatusError( status ) )
				break;
			if( envelopeInfoPtr->hasIndefiniteTrailer )
				{
				/* The trailer has an indefinite length, write the EOC for
				   the trailer to the output */
				writeEndIndef( &envelopeInfoPtr->auxStream );
				if( copyFromAuxStream( envelopeInfoPtr ) )
					status = CRYPT_ERROR_OVERFLOW;
				}
			state = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \
					  envelopeInfoPtr->hasIndefiniteTrailer ) ? \
					ENVSTATE_EOC : ENVSTATE_DONE;
			}

		/* Handle the final end-of-contents octets */
		if( state == ENVSTATE_EOC )
			{
			/* Write the end-of-contents octets for the OCTET STRING/SEQUENCE,
			   [0], and SEQUENCE if necessary */
			writeEndIndef( &envelopeInfoPtr->auxStream );
			writeEndIndef( &envelopeInfoPtr->auxStream );
			writeEndIndef( &envelopeInfoPtr->auxStream );
			if( copyFromAuxStream( envelopeInfoPtr ) )
				status = CRYPT_ERROR_OVERFLOW;

			/* We're done */
			state = ENVSTATE_DONE;
			}
		}

	/* Remember the state information */
	envelopeInfoPtr->envState = state;

	/* Now that we've written the final end-of-contents octets, set the end-
	   of-segment-data pointer to the end of the data in the buffer so
	   copyFromEnvelope() can copy out the remaining data */
	if( cryptStatusOK( status ) && state == ENVSTATE_DONE )
		envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;

	return( status );
	}

/****************************************************************************
*																			*
*							Envelope Access Routines						*
*																			*
****************************************************************************/

void initCMSEnveloping( ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Set the access method pointers */
	envelopeInfoPtr->emitPreamble = emitPreamble;
	envelopeInfoPtr->emitPostamble = emitPostamble;
	envelopeInfoPtr->checkCryptAlgo = checkCryptAlgo;
	envelopeInfoPtr->checkHashAlgo = checkHashAlgo;

	/* Set up the processing state information */
	envelopeInfoPtr->envState = ENVSTATE_NONE;

	/* Remember the current default settings for use with the envelope.  
	   We force the use of the CBC encryption mode because this is the 
	   safest and most efficient encryption mode, and the only mode defined 
	   for many CMS algorithms.  Since the CMS algorithms represent only a 
	   subset of what's available, we have to drop back to fixed values if 
	   the caller has selected something exotic */
	krnlSendMessage( envelopeInfoPtr->ownerHandle, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, 
					 &envelopeInfoPtr->defaultHash, CRYPT_OPTION_ENCR_HASH );
	if( !checkAlgoID( envelopeInfoPtr->defaultHash, CRYPT_MODE_NONE ) )
		envelopeInfoPtr->defaultHash = CRYPT_ALGO_SHA;
	krnlSendMessage( envelopeInfoPtr->ownerHandle, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, 
					 &envelopeInfoPtr->defaultAlgo, CRYPT_OPTION_ENCR_ALGO );
	if( !checkAlgoID( envelopeInfoPtr->defaultAlgo,
					  ( envelopeInfoPtr->defaultAlgo == CRYPT_ALGO_RC4 ) ? \
					  CRYPT_MODE_OFB : CRYPT_MODE_CBC ) )
		envelopeInfoPtr->defaultAlgo = CRYPT_ALGO_3DES;
	krnlSendMessage( envelopeInfoPtr->ownerHandle, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, 
					 &envelopeInfoPtr->defaultMAC, CRYPT_OPTION_ENCR_MAC );
	if( !checkAlgoID( envelopeInfoPtr->defaultMAC, CRYPT_MODE_NONE ) )
		envelopeInfoPtr->defaultMAC = CRYPT_ALGO_HMAC_SHA;
	}

⌨️ 快捷键说明

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