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

📄 cmp_wr.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Determine how big the sender and recipient info will be.  We 
	   shouldn't need to send a recipient name for an ir because it won't
	   usually be known yet, but various implementations can't handle a zero-
	   length GeneralName, so we supply it if it's available even though it's 
	   redundant */
	if( useFullHeader )
		{
		/* Get the sender DN info */
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( senderNameObject, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_SUBJECT );
		if( status == CRYPT_ERROR_NOTFOUND && !isServer( sessionInfoPtr ) && \
			protocolInfo->operation == CTAG_PB_IR )
			{
			/* If there's no subject DN present and it's the first message 
			   in a client's ir exchange, this isn't an error because the 
			   subject may not know their DN yet (at least that's the 
			   theory, most servers will reject a message with no sender 
			   name) */
			if( sessionInfoPtr->iCertResponse == CRYPT_ERROR )
				{
				senderNameObject = CRYPT_ERROR;
				msgData.length = ( int ) sizeofObject( 0 );
				status = CRYPT_OK;
				}
			else
				{
				/* Try again with the response from the server, which 
				   contains our newly-allocated DN */
				senderNameObject = sessionInfoPtr->iCertResponse;
				status = krnlSendMessage( senderNameObject,
										  IMESSAGE_GETATTRIBUTE_S, &msgData,
										  CRYPT_IATTRIBUTE_SUBJECT );
				}
			}
		if( cryptStatusError( status ) )
			return( status );
		senderNameLength = msgData.length;

		/* Get the recipient DN info */
		setMessageData( &msgData, NULL, 0 );
		if( recipNameObject != CRYPT_ERROR )
			status = krnlSendMessage( recipNameObject,
									  IMESSAGE_GETATTRIBUTE_S, &msgData,
									  CRYPT_IATTRIBUTE_SUBJECT );
		else
			{
			/* If we're sending an error response there may not be any 
			   recipient name information present yet if the error occurred 
			   before the recipient information could be established, and if 
			   this is a MAC-authenticated PKIBoot we don't have the CA's 
			   cert yet so we don't know its DN.  To work around this we 
			   send a zero-length DN (this is one of those places where an 
			   optional field is specified as being mandatory, to lend 
			   balance to the places where mandatory fields are specified as 
			   optional) */
			msgData.length = ( int ) sizeofObject( 0 );
			}
		if( cryptStatusError( status ) )
			return( status );
		recipNameLength = msgData.length;
		}
	else
		{
		/* We're not using sender or recipient info since it doesn't serve 
		   any useful purpose, just set the fields to an empty SEQUENCE */
		senderNameLength = recipNameLength = sizeofObject( 0 );
		}

	/* Determine how big the remaining header data will be */
	sMemNullOpen( &nullStream );
	if( protocolInfo->useMACsend )
		{
		writeMacInfo( &nullStream, protocolInfo, 
					  sessionInfoPtr->protocolFlags & CMP_PFLAG_MACINFOSENT );
		}
	else
		{
		writeContextAlgoID( &nullStream, protocolInfo->authContext, 
							protocolInfo->hashAlgo );
		}
	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 ) && \
		( ( isServer( sessionInfoPtr ) && \
			protocolInfo->operation == CTAG_PB_GENM ) || \
		  !protocolInfo->useMACsend ) )
		{
		attributeLength += writeCertID( NULL, protocolInfo->authContext );
		sendCertID = TRUE;
		}
	totalLength = sizeofShortInteger( CMP_VERSION ) + \
				  objSize( senderNameLength ) + objSize( recipNameLength ) + \
				  objSize( protInfoLength ) + \
				  objSize( sizeofObject( protocolInfo->transIDsize ) );
	if( ( useFullHeader || \
		  !( sessionInfoPtr->protocolFlags & CMP_PFLAG_USERIDSENT ) ) && \
		( protocolInfo->userIDsize > 0 ) )
		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 );
			if( cryptStatusError( status ) )
				return( status );
			}
		else
			writeSequence( stream, 0 );
		writeConstructed( stream, recipNameLength, 4 );
		if( recipNameObject != CRYPT_ERROR )
			{
			status = exportAttributeToStream( stream, recipNameObject, 
											  CRYPT_IATTRIBUTE_SUBJECT );
			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, senderNameLength, 4 );
		writeSequence( stream, 0 );
		writeConstructed( stream, recipNameLength, 4 );
		writeSequence( stream, 0 );
		}

	/* 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 );
		}
	if( ( useFullHeader || \
		  !( sessionInfoPtr->protocolFlags & CMP_PFLAG_USERIDSENT ) ) && \
		( protocolInfo->userIDsize > 0 ) )
		{
		/* We're using full headers or we're the client sending our first
		   message, identify the sender key.  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->userIDsize ),
						  CTAG_PH_SENDERKID );
		writeOctetString( stream, protocolInfo->userID,
						  protocolInfo->userIDsize, DEFAULT_TAG );
		sessionInfoPtr->protocolFlags |= CMP_PFLAG_USERIDSENT;
		}
	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 + 8 ], headerBuffer[ 8 + 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( isServer( sessionInfoPtr ) )
					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, sizeofNull(), CTAG_PB_PKICONF );
				status = writeNull( &stream, DEFAULT_TAG );
				break;

			case CMPBODY_GENMSG:
				if( isServer( sessionInfoPtr ) )
					status = writeGenMsgBody( &stream, sessionInfoPtr );
				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:
				retIntError();
			}
		}
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		return( status );
		}

	/* Generate the MAC or signature as appropriate */
	if( protocolInfo->useMACsend )
		{
		status = writeMacProtinfo( protocolInfo->iMacContext,
						sessionInfoPtr->receiveBuffer, stell( &stream ),
						protInfo, 64 + MAX_PKCENCRYPTED_SIZE, &protInfoSize );
		}
	else
		{
		status = writeSignedProtinfo( protocolInfo->authContext, 
						protocolInfo->hashAlgo, 
						sessionInfoPtr->receiveBuffer, stell( &stream ),
						protInfo, 64 + MAX_PKCENCRYPTED_SIZE, &protInfoSize );
		}
	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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -