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

📄 env_cms.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
								 CRYPT_CERTINFO_CMS_CONTENTTYPE );
			krnlSendMessage( actionListPtr->iExtraData,
							 IMESSAGE_SETATTRIBUTE, 
							 &envelopeInfoPtr->contentType,
							 CRYPT_CERTINFO_CMS_CONTENTTYPE );
			}
		}

	/* 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 us, 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, IMESSAGE_GETATTRIBUTE, 
						 &useDefaultAttributes, 
						 CRYPT_OPTION_CMS_DEFAULTATTRIBUTES );
		signingAttributes = useDefaultAttributes ? \
							CRYPT_USE_DEFAULT : CRYPT_UNUSED;
		}

	/* Evaluate the size of the exported action */
	status = iCryptCreateSignatureEx( NULL, &signatureSize, 0,
						envelopeInfoPtr->type, actionListPtr->iCryptHandle,
						actionListPtr->associatedAction->iCryptHandle,
						signingAttributes, 
						( actionListPtr->iTspSession != CRYPT_ERROR ) ? \
							actionListPtr->iTspSession : CRYPT_UNUSED );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( actionListPtr->iCryptHandle, 
								  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 that will result in indefinite-
		   length encodings present, we can't use a definite-length encoding 
		   for the signature */
		envelopeInfoPtr->dataFlags |= ENVDATA_HASINDEFTRAILER;
		actionListPtr->encodedSize = CRYPT_UNUSED;
		}
	else
		{
		actionListPtr->encodedSize = signatureSize;
		envelopeInfoPtr->signActionSize += signatureSize;
		}

	return( CRYPT_OK );
	}

static int preEnvelopeSign( ENVELOPE_INFO *envelopeInfoPtr )
	{
	ACTION_LIST *actionListPtr = envelopeInfoPtr->postActionList;
	int status;

	/* Make sure that there's at least one signing action present */
	if( actionListPtr == NULL )
		return( CRYPT_ERROR_NOTINITED );

	/* If we're generating a detached signature, the content is supplied
	   externally and has zero size */
	if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
		envelopeInfoPtr->payloadSize = 0;

	/* If it's an attributes-only message, it must be zero-length CMS signed 
	   data with signing attributes present */
	if( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY )
		{
		if( envelopeInfoPtr->type != CRYPT_FORMAT_CMS || \
			actionListPtr->iExtraData == CRYPT_ERROR )
			return( CRYPT_ERROR_NOTINITED );
		if( envelopeInfoPtr->payloadSize > 0 )
			return( CRYPT_ERROR_INITED );
		}

	/* If it's a CMS envelope we have to write the signing cert chain 
	   alongside the signatures as extra data unless it's explicitly 
	   excluded, so we record how large the info will be for later */
	if( ( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \
		  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) && \
		!( envelopeInfoPtr->flags & ENVELOPE_NOSIGNINGCERTS ) )
		{
		if( actionListPtr->next != NULL )
			{
			MESSAGE_CREATEOBJECT_INFO createInfo;

			/* There are multiple sets of signing certs present, create a 
			   signing-cert meta-object to hold the overall set of certs */
			setMessageCreateObjectInfo( &createInfo, 
										CRYPT_CERTTYPE_CERTCHAIN );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
									  IMESSAGE_DEV_CREATEOBJECT,
									  &createInfo, OBJECT_TYPE_CERTIFICATE );
			if( cryptStatusError( status ) )
				return( status );
			envelopeInfoPtr->iExtraCertChain = createInfo.cryptHandle;
			}
		else
			{
			RESOURCE_DATA msgData;

			/* There's a single signing cert present, determine its size */
			setMessageData( &msgData, NULL, 0 );
			status = krnlSendMessage( actionListPtr->iCryptHandle, 
									  IMESSAGE_CRT_EXPORT, &msgData,
									  CRYPT_ICERTFORMAT_CERTSET );
			if( cryptStatusError( status ) )
				return( status );
			envelopeInfoPtr->extraDataSize = msgData.length;
			}
		}

	/* Evaluate the size of each signature action */
	for( actionListPtr = envelopeInfoPtr->postActionList; actionListPtr != NULL;
		 actionListPtr = actionListPtr->next )
		{
		status = processSignatureAction( envelopeInfoPtr, actionListPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
		{
		RESOURCE_DATA msgData;

		/* We're writing the signing cert chain and there are multiple 
		   signing certs present, get the size of the overall cert 
		   collection */
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,
								  IMESSAGE_CRT_EXPORT, &msgData,
								  CRYPT_ICERTFORMAT_CERTSET );
		if( cryptStatusError( status ) )
			return( status );
		envelopeInfoPtr->extraDataSize = msgData.length;
		}

	/* Hashing is now active */
	envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;

	return( CRYPT_OK );
	}

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

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

static int emitPreamble( ENVELOPE_INFO *envelopeInfoPtr )
	{
	int status = CRYPT_OK;

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

	/* If we haven't started doing anything yet, perform various final
	   initialisations */
	if( envelopeInfoPtr->envState == 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 such as automatically-added hash 
		   actions that were overridden with user-supplied alternate 
		   actions */
		deleteUnusedActions( envelopeInfoPtr );

		/* We're ready to go, prepare to emit the outer header */
		envelopeInfoPtr->envState = ENVSTATE_HEADER;
		assert( actionsOK( envelopeInfoPtr ) );
		}

	/* Emit the outer header.  This always follows directly from the final
	   initialisation step, but we keep the two logically distinct to 
	   emphasise that the former is merely finalised enveloping actions
	   without performing any header processing, while the latter is that
	   first stage that actually emits header data */
	if( envelopeInfoPtr->envState == ENVSTATE_HEADER )
		{
		STREAM stream;

		/* If we're encrypting, set up the encryption-related information */
		if( envelopeInfoPtr->usage == ACTION_CRYPT )
			{
			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.  The
		   DigestedData/ACTION_HASH 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 = writeSignedDataHeader( &stream, envelopeInfoPtr, 
												TRUE );
				break;

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

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

			case ACTION_NONE:
				status = writeCMSheader( &stream, 
								getContentOID( envelopeInfoPtr->contentType ),
								envelopeInfoPtr->payloadSize, FALSE );
				break;

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

			default:
				assert( NOTREACHED );
			}
		envelopeInfoPtr->bufPos = 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 that 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->dataFlags |= ENVDATA_SEGMENTCOMPLETE;
			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 );
		envelopeInfoPtr->envState = ENVSTATE_KEYINFO;
		}

	/* Handle key export actions */
	if( envelopeInfoPtr->envState == ENVSTATE_KEYINFO )
		{
		const CRYPT_CERTIFICATE iExtraCertChain = \
					( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR ) ? \
					envelopeInfoPtr->iExtraCertChain : CRYPT_UNUSED;
		ACTION_LIST *lastActionPtr;

		/* 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 */
		for( lastActionPtr = envelopeInfoPtr->lastAction; 
			 lastActionPtr != NULL; lastActionPtr = lastActionPtr->next )
			{
			const CRYPT_FORMAT_TYPE formatType = \
						( lastActionPtr->action == ACTION_KEYEXCHANGE ) ? \
						CRYPT_FORMAT_CMS : envelopeInfoPtr->type;
			void *bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;
			const int dataLeft = min( envelopeInfoPtr->bufSize - \
									  envelopeInfoPtr->bufPos, 8192 );
			int keyexSize;

			/* Make sure that there's enough room to emit this key exchange 
			   action */
			if( lastActionPtr->encodedSize + 128 > dataLeft )
				{
				status = CRYPT_ERROR_OVERFLOW;
				break;
				}

			/* Emit the key exchange action */
			status = iCryptExportKeyEx( envelopeInfoPtr->buffer + \
										envelopeInfoPtr->bufPos, &keyexSize, 
										dataLeft, formatType, 
										envelopeInfoPtr->iCryptContext,
										lastActionPtr->iCryptHandle, 
										iExtraCertChain );
			if( cryptStatusError( status ) )
				break;
			envelopeInfoPtr->bufPos += keyexSize;
			}
		envelopeInfoPtr->lastAction = lastActionPtr;
		if( cryptStatusError( status ) )
			return( status );

		/* If it's an indefinite-length header, close off the set of key 
		   exchange actions */
		if( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED )

⌨️ 快捷键说明

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