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

📄 cmp_rd.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
									CRYPT_MAX_TEXTSIZE, ATTR_FLAG_NONE );
			}
		if( cryptStatusOK( status ) && isServerInitialMessage && useMAC )
			status = initServerAuthentMAC( sessionInfoPtr, protocolInfo );
		}
	if( cryptStatusOK( status ) && protocolInfo->certIDchanged )
		{
		status = addSessionInfo( &sessionInfoPtr->attributeList,
								 CRYPT_SESSINFO_SERVER_FINGERPRINT,
								 protocolInfo->certID,
								 protocolInfo->certIDsize );
		if( cryptStatusOK( status ) && isServerInitialMessage )
			status = initServerAuthentSign( sessionInfoPtr, protocolInfo );
		}
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}

	/* Determine the message body type.  An error response can occur at any
	   point in an exchange so we process this immediately.  We don't do an
	   integrity verification at this point since it's not certain what we
	   should report if the check fails, and an unauthenticated error
	   message is better than an authenticated paketewhainau */
	tag = peekTag( &stream );
	if( cryptStatusError( tag ) )
		return( tag );
	tag = EXTRACT_CTAG( tag );
	if( tag == CTAG_PB_ERROR )
		{
		status = readErrorBody( &stream, sessionInfoPtr );
		sMemDisconnect( &stream );
		return( status );
		}

	/* If this is an initial message we don't know what to expect yet so we
	   set the type to whatever we find, as long as it's a valid message to
	   send to a CA */
	if( isServerInitialMessage && \
		( tag == CTAG_PB_IR || tag == CTAG_PB_CR || tag == CTAG_PB_P10CR || \
		  tag == CTAG_PB_KUR || tag == CTAG_PB_RR || tag == CTAG_PB_GENM ) )
		protocolInfo->operation = messageType = tag;

	/* If we're using a MAC for authentication, we can finally set up the
	   MAC info using the appropriate password */
	if( useMAC )
		{
		const ATTRIBUTE_LIST *passwordPtr = \
					findSessionInfo( sessionInfoPtr->attributeList,
									 CRYPT_SESSINFO_PASSWORD );
		BYTE decodedValue[ 64 + 8 ];
		const BYTE *decodedValuePtr = decodedValue;
		int decodedValueLength;

		if( passwordPtr->flags & ATTR_FLAG_ENCODEDVALUE )
			{
			/* It's an encoded value, get the decoded form */
			status = decodePKIUserValue( decodedValue, 64, 
										 &decodedValueLength, 
										 passwordPtr->value, 
										 passwordPtr->valueLength );
			if( cryptStatusError( status ) )
				{
				assert( DEBUG_WARN );
				sMemDisconnect( &stream );
				retExt( status,
						( status, SESSION_ERRINFO, 
						  "Invalid PKI user password" ) );
				}
			}
		else
			{
			decodedValuePtr = passwordPtr->value;
			decodedValueLength = passwordPtr->valueLength;
			}

		/* We couldn't initialise the MAC information when we read the
		   header because the order of the information used to set this up
		   is backwards, so we have to go back and re-process it now */
		if( cryptStatusOK( status ) )
			{
			const int streamPos = stell( &stream );

			sseek( &stream, protocolInfo->macInfoPos );
			status = readMacInfo( &stream, protocolInfo, decodedValuePtr,
								  decodedValueLength, SESSION_ERRINFO );
			sseek( &stream, streamPos );
			}
		zeroise( decodedValue, CRYPT_MAX_TEXTSIZE );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( &stream );
			return( status );
			}
		}

	/* Make sure that it's what we're after, remember where the message body
	   starts, and skip it (it'll be processed after we verify its integrity) */
	if( tag != messageType )
		{
		sMemDisconnect( &stream );
		protocolInfo->pkiFailInfo = CMPFAILINFO_BADREQUEST;
		if( isServerInitialMessage )
			{
			/* This is the first message and we got no recognisable message
			   of any type */
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "Invalid message type %d", tag ) );
			}
		retExt( CRYPT_ERROR_BADDATA,
				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
				  "Invalid message type, expected %d, got %d", messageType,
				  tag ) );
		}
	status = readConstructed( &stream, &length, messageType );
	if( cryptStatusOK ( status ) )
		{
		bodyStart = stell( &stream );
		status = sSkip( &stream, length );
		}
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		protocolInfo->pkiFailInfo = CMPFAILINFO_BADDATAFORMAT;
		retExt( CRYPT_ERROR_BADDATA,
				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
				  "Invalid message body start" ) );
		}

	/* Read the start of the message integrity info */
	protPartSize = stell( &stream ) - protPartStart;
	status = readConstructed( &stream, &integrityInfoLength,
							  CTAG_PM_PROTECTION );
	if( cryptStatusOK( status ) )
		{
		status = sMemGetDataBlock( &stream, &integrityInfoPtr, 
								   integrityInfoLength );
		if( cryptStatusError( status ) )
			{
			/* If there integrity protection is missing, report it as a 
			   wrong-integrity-info problem, the closest we can get to the 
			   real error.  This has already been checked by the high-level 
			   PKI datagram read code anyway, but we check gain here just to 
			   be safe */
			protocolInfo->pkiFailInfo = CMPFAILINFO_WRONGINTEGRITY;
			setErrorString( errorInfo, 
							"Signature/MAC data is missing or truncated", 
							42 );
			status = CRYPT_ERROR_SIGNATURE;
			}
		}
	if( cryptStatusOK( status ) && tag == CTAG_PB_IR && !useMAC )
		{
		/* An ir has to be MAC'ed, in theory this doesn't really matter but
		   the spec requires that we only allow a MAC.  If it's not MAC'ed it
		   has to be a cr, which is exactly the same only different */
		protocolInfo->pkiFailInfo = CMPFAILINFO_WRONGINTEGRITY;
		setErrorString( errorInfo, 
						"Received signed ir, should be MAC'ed", 36 );
		status = CRYPT_ERROR_SIGNATURE;
		}
	if( cryptStatusOK( status ) && tag == CTAG_PB_RR && useMAC )
		{
		/* An rr can't be MAC'ed because the trail from the original PKI
		   user to the cert being revoked can become arbitrarily blurred,
		   with the cert being revoked having a different DN,
		   issuerAndSerialNumber, and public key after various updates,
		   replacements, and reissues.  In fact cryptlib tracks the
		   resulting directed graph via the cert store log and allows
		   fetching the original authorising issuer of a cert using the
		   KEYMGMT_FLAG_GETISSUER option, however this requires that the
		   client also be running cryptlib, or specifically that it submit
		   a cert ID in the request, this being the only identifier that
		   reliably identifies the cert being revoked.  Since it's somewhat
		   unsound to assume this, we don't currently handle MAC'ed rr's,
		   however everything is in place to allow them to be implemented
		   if they're really needed */
		protocolInfo->pkiFailInfo = CMPFAILINFO_WRONGINTEGRITY;
		setErrorString( errorInfo, 
						"Received MAC'ed rr, should be signed", 36 );
		status = CRYPT_ERROR_SIGNATURE;
		}
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}

	/* Verify the message integrity */
	if( protocolInfo->useMACreceive )
		{
		const CRYPT_CONTEXT iMacContext = ( protocolInfo->useAltMAC ) ? \
					protocolInfo->iAltMacContext : protocolInfo->iMacContext;
		void *protectionPtr = DUMMY_INIT_PTR;
		int protectionLength;

		/* Read the BIT STRING encapsulation, MAC the data, and make sure
		   that it matches the value attached to the message */
		status = readBitStringHole( &stream, &protectionLength, 16, 
									DEFAULT_TAG );
		if( cryptStatusOK( status ) )
			status = sMemGetDataBlock( &stream, &protectionPtr, 
									   protectionLength );
		if( cryptStatusOK( status ) && \
			( protectionLength < 16 || \
			  protectionLength > CRYPT_MAX_HASHSIZE ) )
			status = CRYPT_ERROR_BADDATA;
		if( cryptStatusOK( status ) )
			status = hashMessageContents( iMacContext,
							sessionInfoPtr->receiveBuffer + protPartStart,
							protPartSize );
		if( cryptStatusOK( status ) )
			{
			MESSAGE_DATA msgData;

			setMessageData( &msgData, protectionPtr, protectionLength );
			if( cryptStatusError( \
				krnlSendMessage( iMacContext, IMESSAGE_COMPARE, &msgData,
								 MESSAGE_COMPARE_HASH ) ) )
				status = CRYPT_ERROR_SIGNATURE;
			}
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( &stream );
			retExt( CRYPT_ERROR_SIGNATURE,
					( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, 
					  "Bad message MAC" ) );
			}
		}
	else
		{
		if( !protocolInfo->isCryptlib )
			{
			MESSAGE_DATA msgData;

			/* Make sure that the sig-check key that we'll be using is the
			   correct one.  Because of CMP's use of a raw signature format
			   we have to do this manually rather than relying on the sig-
			   check code to do it for us, and because of the braindamaged
			   way of identifying integrity-protection keys for non-cryptlib
			   messages even this isn't enough to definitely tell us that
			   we're using the right key, in which case we'll get a bad data
			   or bad sig response from the sig check code */
			setMessageData( &msgData, protocolInfo->senderDNPtr,
							protocolInfo->senderDNlength );
			status = krnlSendMessage( sessionInfoPtr->iAuthInContext,
									  IMESSAGE_COMPARE, &msgData,
									  MESSAGE_COMPARE_SUBJECT );
			if( cryptStatusError( status ) )
				{
				/* A failed comparison is reported as a generic CRYPT_ERROR,
				   convert it into a wrong-key error if necessary */
				sMemDisconnect( &stream );
				retExt( ( status == CRYPT_ERROR ) ? \
						CRYPT_ERROR_WRONGKEY : status,
						( ( status == CRYPT_ERROR ) ? \
						  CRYPT_ERROR_WRONGKEY : status, SESSION_ERRINFO, 
						  "Message signature key doesn't match our "
						  "signature check key, signature can't be "
						  "checked" ) );
				}
			}

		/* Hash the data and verify 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 + protPartStart,
							protPartSize );
			if( cryptStatusOK( status ) )
				{
				status = checkRawSignature( integrityInfoPtr, 
											integrityInfoLength,
											sessionInfoPtr->iAuthInContext,
											createInfo.cryptHandle );
				}
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			if( cryptStatusError( status ) )
				{
				sMemDisconnect( &stream );
				retExt( CRYPT_ERROR_SIGNATURE,
						( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, 
						  "Bad message signature" ) );
				}
			}
		}
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}
	sseek( &stream, bodyStart );

	/* If it's a client request, import the encapsulated request data */
	switch( messageType )
		{
		case CTAG_PB_IR:
		case CTAG_PB_CR:
		case CTAG_PB_P10CR:
		case CTAG_PB_KUR:
		case CTAG_PB_RR:
			status = readRequestBody( &stream, sessionInfoPtr, protocolInfo,
									  messageType );
			break;

		case CTAG_PB_IP:
		case CTAG_PB_CP:
		case CTAG_PB_KUP:
		case CTAG_PB_RP:
			status = readResponseBody( &stream, sessionInfoPtr,
									   protocolInfo );
			break;

		case CTAG_PB_CERTCONF:
			status = readConfBody( &stream, sessionInfoPtr, protocolInfo );
			break;

		case CTAG_PB_PKICONF:
			/* If it's a confirmation there's no message body and we're
			   done */
			break;

		case CTAG_PB_GENM:
		case CTAG_PB_GENP:
			status = readGenMsgBody( &stream, sessionInfoPtr,
									 messageType == CTAG_PB_GENM );
			break;

		default:
			assert( DEBUG_WARN );
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "Unexpected message type %d", messageType ) );
		}
	sMemDisconnect( &stream );
	return( status );
	}
#endif /* USE_CMP */

⌨️ 快捷键说明

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