cmp_wr.c

来自「cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和」· C语言 代码 · 共 960 行 · 第 1/3 页

C
960
字号
					  sessionInfoPtr->protocolFlags & CMP_PFLAG_MACINFOSENT );
	else
		writeContextAlgoID( &nullStream, protocolInfo->authContext, 
							protocolInfo->hashAlgo, 
							ALGOID_FLAG_ALGOID_ONLY );
	protInfoLength = stell( &nullStream );
	sMemClose( &nullStream );
	if( !( sessionInfoPtr->protocolFlags & CMP_PFLAG_CLIBIDSENT ) )
		{
		attributeLength += sizeofObject( \
								sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
								sizeofObject( 0 ) );
		sendClibID = TRUE;
		}
	if( !( sessionInfoPtr->protocolFlags & CMP_PFLAG_CERTIDSENT ) && \
		( ( ( sessionInfoPtr->flags & SESSION_ISSERVER ) && \
			protocolInfo->operation == CTAG_PB_GENM ) || \
		  !protocolInfo->useMACsend ) )
		{
		attributeLength += writeCertID( NULL, protocolInfo->authContext );
		sendCertID = TRUE;
		}
	totalLength = sizeofShortInteger( CMP_VERSION ) + \
				  objSize( senderNameLength ) + objSize( recipNameLength ) + \
				  objSize( protInfoLength );
	if( protocolInfo->transIDsize > 0 )
		totalLength += objSize( sizeofObject( protocolInfo->transIDsize ) );
	if( useFullHeader || \
		!( sessionInfoPtr->protocolFlags & CMP_PFLAG_USERIDSENT ) )
		totalLength += objSize( sizeofObject( protocolInfo->userIDsize ) );
	if( useFullHeader )
		totalLength += ( protocolInfo->senderNonceSize > 0 ? \
						 objSize( sizeofObject( protocolInfo->senderNonceSize ) ) : 0 ) + \
					   ( protocolInfo->recipNonceSize > 0 ? \
						 objSize( sizeofObject( protocolInfo->recipNonceSize ) ) : 0 );
	if( attributeLength > 0 )
		totalLength += objSize( objSize( attributeLength ) );
	if( sizeofObject( totalLength ) > sMemDataLeft( stream ) )
		return( CRYPT_ERROR_OVERFLOW );

	/* Write the PKI header wrapper, version info, and sender and recipient
	   names if there's name information present */
	writeSequence( stream, totalLength );
	writeShortInteger( stream, CMP_VERSION, DEFAULT_TAG );
	if( useFullHeader )
		{
		writeConstructed( stream, senderNameLength, 4 );
		if( senderNameObject != CRYPT_ERROR )
			{
			status = exportAttributeToStream( stream, senderNameObject, 
											  CRYPT_IATTRIBUTE_SUBJECT,
											  CRYPT_USE_DEFAULT );
			if( cryptStatusError( status ) )
				return( status );
			}
		else
			writeSequence( stream, 0 );
		writeConstructed( stream, recipNameLength, 4 );
		if( recipNameObject != CRYPT_ERROR )
			{
			status = exportAttributeToStream( stream, recipNameObject, 
											  CRYPT_IATTRIBUTE_SUBJECT,
											  CRYPT_USE_DEFAULT );
			if( cryptStatusError( status ) )
				return( status );
			}
		else
			writeSequence( stream, 0 );
		}
	else
		{
		/* This is one of the portions of CMP where an optional field is 
		   marked as mandatory, to balance out the mandatory fields that are 
		   marked as optional.  To work around this, we write the names as 
		   zero-length DNs */
		writeConstructed( stream, 0, 4 );
		writeConstructed( stream, 0, 4 );
		}

	/* Write the protection info, assorted nonces and IDs, and extra
	   information that the other side may be able to make use of */
	writeConstructed( stream, protInfoLength, CTAG_PH_PROTECTIONALGO );
	if( protocolInfo->useMACsend )
		{
		writeMacInfo( stream, protocolInfo, 
					  sessionInfoPtr->protocolFlags & CMP_PFLAG_MACINFOSENT );
		sessionInfoPtr->protocolFlags |= CMP_PFLAG_MACINFOSENT;
		}
	else
		writeContextAlgoID( stream, protocolInfo->authContext, 
							protocolInfo->hashAlgo, 
							ALGOID_FLAG_ALGOID_ONLY );
	if( useFullHeader || \
		!( sessionInfoPtr->protocolFlags & CMP_PFLAG_USERIDSENT ) )
		{
		/* We're using full headers or we're the client sending our first
		   message, identify the sender key */
		writeConstructed( stream, objSize( protocolInfo->userIDsize ),
						  CTAG_PH_SENDERKID );
		writeOctetString( stream, protocolInfo->userID,
						  protocolInfo->userIDsize, DEFAULT_TAG );
		sessionInfoPtr->protocolFlags |= CMP_PFLAG_USERIDSENT;
		}
	if( protocolInfo->transIDsize > 0 )
		{
		/* If we're sending an error response to an initial message that we 
		   couldn't even start to parse, the transaction ID won't be present
		   yet so we only send this if it's present */
		writeConstructed( stream, objSize( protocolInfo->transIDsize ),
						  CTAG_PH_TRANSACTIONID );
		status = writeOctetString( stream, protocolInfo->transID,
								   protocolInfo->transIDsize, DEFAULT_TAG );
		}
	if( useFullHeader )
		{
		if( protocolInfo->senderNonceSize > 0 )
			{
			writeConstructed( stream, 
							  objSize( protocolInfo->senderNonceSize ),
							  CTAG_PH_SENDERNONCE );
			status = writeOctetString( stream, protocolInfo->senderNonce,
									   protocolInfo->senderNonceSize, 
									   DEFAULT_TAG );
			}
		if( protocolInfo->recipNonceSize > 0 )
			{
			writeConstructed( stream, 
							  objSize( protocolInfo->recipNonceSize ),
							  CTAG_PH_RECIPNONCE );
			status = writeOctetString( stream, protocolInfo->recipNonce,
									   protocolInfo->recipNonceSize, 
									   DEFAULT_TAG );
			}
		}
	if( attributeLength > 0 )
		{
		assert( sendClibID || sendCertID );

		/* We haven't sent any messages yet, let the other side know that 
		   we're running cryptlib and identify our signing cert */
		writeConstructed( stream, objSize( attributeLength ),
						  CTAG_PH_GENERALINFO );
		status = writeSequence( stream, attributeLength );
		if( sendClibID )
			{
			writeSequence( stream, sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
								   sizeofObject( 0 ) );
			writeOID( stream, OID_CRYPTLIB_PRESENCECHECK );
			status = writeSet( stream, 0 );
			sessionInfoPtr->protocolFlags |= CMP_PFLAG_CLIBIDSENT;
			}
		if( sendCertID )
			{
			status = writeCertID( stream, protocolInfo->authContext );
			sessionInfoPtr->protocolFlags |= CMP_PFLAG_CERTIDSENT;
			}
		}
	return( status );
	}

/****************************************************************************
*																			*
*							Write a PKI Message								*
*																			*
****************************************************************************/

/* Write a PKI message:

	PkiMessage ::= SEQUENCE {
		header			PKIHeader,
		body			CHOICE { [0]... [24]... },
		protection	[0]	BIT STRING
		} */

int writePkiMessage( SESSION_INFO *sessionInfoPtr,
					 CMP_PROTOCOL_INFO *protocolInfo,
					 const CMPBODY_TYPE bodyType )
	{
	BYTE protInfo[ 64 + MAX_PKCENCRYPTED_SIZE ], headerBuffer[ 8 ];
	STREAM stream;
	int headerSize, protInfoSize, status;

	/* Write the header and payload so that we can MAC/sign it */
	sMemOpen( &stream, sessionInfoPtr->receiveBuffer,
			  sessionInfoPtr->receiveBufSize );
	status = writePkiHeader( &stream, sessionInfoPtr, protocolInfo );
	if( cryptStatusOK( status ) )
		{
		switch( bodyType )
			{
			case CMPBODY_NORMAL:
				if( sessionInfoPtr->flags & SESSION_ISSERVER )
					status = writeResponseBody( &stream, sessionInfoPtr,
												protocolInfo );
				else
					status = writeRequestBody( &stream, sessionInfoPtr,
											   protocolInfo );
				break;

			case CMPBODY_CONFIRMATION:
				status = writeConfBody( &stream, sessionInfoPtr,
										protocolInfo );
				break;

			case CMPBODY_ACK:
				writeConstructed( &stream, objSize( sizeofNull() ),
								  CTAG_PB_PKICONF );
				writeSequence( &stream, sizeofNull() );
				status = writeNull( &stream, DEFAULT_TAG );
				break;

			case CMPBODY_GENMSG:
				if( sessionInfoPtr->flags & SESSION_ISSERVER )
					status = writeGenMsgBody( &stream, sessionInfoPtr,
											  protocolInfo );
				else
					{
					writeConstructed( &stream,
							objSize( objSize( sizeofOID( OID_PKIBOOT ) ) ),
							CTAG_PB_GENM );
					writeSequence( &stream,
								   objSize( sizeofOID( OID_PKIBOOT ) ) );
					writeSequence( &stream, sizeofOID( OID_PKIBOOT ) );
					status = writeOID( &stream, OID_PKIBOOT );
					}
				break;

			case CMPBODY_ERROR:
				status = writeErrorBody( &stream, protocolInfo );
				break;

			default:
				assert( NOTREACHED );
			}
		}
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		return( status );
		}

	/* Generate the MAC or signature as appropriate */
	if( protocolInfo->useMACsend )
		{
		BYTE macValue[ CRYPT_MAX_HASHSIZE ];

		status = hashMessageContents( protocolInfo->iMacContext,
						sessionInfoPtr->receiveBuffer, stell( &stream ) );
		if( cryptStatusOK( status ) )
			{
			RESOURCE_DATA msgData;

			setMessageData( &msgData, macValue, CRYPT_MAX_HASHSIZE );
			status = krnlSendMessage( protocolInfo->iMacContext,
									  IMESSAGE_GETATTRIBUTE_S, &msgData,
									  CRYPT_CTXINFO_HASHVALUE );
			protInfoSize = msgData.length;
			}
		if( cryptStatusOK( status ) )
			{
			STREAM macStream;

			/* Write the MAC value with BIT STRING encapsulation */
			sMemOpen( &macStream, protInfo, 64 + MAX_PKCENCRYPTED_SIZE );
			writeBitStringHole( &macStream, protInfoSize, DEFAULT_TAG );
			swrite( &macStream, macValue, protInfoSize );
			protInfoSize = stell( &macStream );
			sMemDisconnect( &macStream );
			}
		}
	else
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		/* Hash the data and create the signature */
		setMessageCreateObjectInfo( &createInfo, protocolInfo->hashAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusOK( status ) )
			{
			status = hashMessageContents( createInfo.cryptHandle,
						sessionInfoPtr->receiveBuffer, stell( &stream ) );
			if( cryptStatusOK( status ) )
				status = createRawSignature( protInfo, &protInfoSize,
											 sizeof( protInfo ),
											 protocolInfo->authContext,
											 createInfo.cryptHandle );
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			}
		}
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		return( status );
		}

	/* Attach the MAC/signature to the payload */
	writeConstructed( &stream, protInfoSize, CTAG_PM_PROTECTION );
	status = swrite( &stream, protInfo, protInfoSize );
	sessionInfoPtr->receiveBufEnd = stell( &stream );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Write the wrapper and move it onto the front of the message */
	sMemOpen( &stream, headerBuffer, 8 );
	writeSequence( &stream, sessionInfoPtr->receiveBufEnd );
	headerSize = stell( &stream );
	sMemDisconnect( &stream );
	memmove( sessionInfoPtr->receiveBuffer + headerSize,
			 sessionInfoPtr->receiveBuffer,
			 sessionInfoPtr->receiveBufEnd );
	memcpy( sessionInfoPtr->receiveBuffer, headerBuffer, headerSize );
	sessionInfoPtr->receiveBufEnd += headerSize;

	return( CRYPT_OK );
	}
#endif /* USE_CMP */

⌨️ 快捷键说明

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