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

📄 cmp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
										  msgData.length, 
										  PROTOCOLINFO_SET_USERID | \
										  PROTOCOLINFO_SET_TRANSID );
			return( status );
			}

		/* It's a cryptlib peer, the cert is identified by an unambiguous 
		   cert ID */
		return( setProtocolInfo( protocolInfo, NULL, 0, 
								 PROTOCOLINFO_SET_TRANSID ) );
		}

	/* If there's a MAC context present from a previous transaction, reuse 
	   it for the current one */
	if( cmpInfo->savedMacContext != CRYPT_ERROR )
		{
		setProtocolInfo( protocolInfo, NULL, 0, PROTOCOLINFO_SET_TRANSID );
		protocolInfo->useMACsend = protocolInfo->useMACreceive = TRUE;
		protocolInfo->iMacContext = cmpInfo->savedMacContext;
		cmpInfo->savedMacContext = CRYPT_ERROR;
		return( CRYPT_OK );
		}

	/* We're using MAC authentication, initialise the protocol info */
	if( userNamePtr->flags & ATTR_FLAG_ENCODEDVALUE )
		{
		BYTE decodedValue[ 64 + 8 ];
		int decodedValueLength;

		/* It's a cryptlib-style encoded user ID, decode it into its binary 
		   value */
		status = decodePKIUserValue( decodedValue, 64, &decodedValueLength,
									 userNamePtr->value, 
									 userNamePtr->valueLength );
		if( cryptStatusError( status ) )
			{
			assert( DEBUG_WARN );
			retExt( status, 
					( status, SESSION_ERRINFO, "Invalid PKI user value" ) );
			}
		status = setProtocolInfo( protocolInfo, decodedValue,
								  decodedValueLength, PROTOCOLINFO_SET_ALL );
		zeroise( decodedValue, CRYPT_MAX_TEXTSIZE );
		}
	else
		{
		/* It's a standard user ID, use it as is */
		status = setProtocolInfo( protocolInfo, userNamePtr->value,
								  userNamePtr->valueLength, 
								  PROTOCOLINFO_SET_ALL );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Set up the MAC context used to authenticate messages */
	if( passwordPtr->flags & ATTR_FLAG_ENCODEDVALUE )
		{
		BYTE decodedValue[ 64 + 8 ];
		int decodedValueLength;

		/* It's a cryptlib-style encoded password, decode it into its binary 
		   value */
		status = decodePKIUserValue( decodedValue, 64, &decodedValueLength,
									 passwordPtr->value, 
									 passwordPtr->valueLength );
		if( cryptStatusError( status ) )
			{
			assert( DEBUG_WARN );
			retExt( status, 
					( status, SESSION_ERRINFO, "Invalid PKI user value" ) );
			}
		status = initMacInfo( protocolInfo->iMacContext, decodedValue, 
							  decodedValueLength, protocolInfo->salt, 
							  protocolInfo->saltSize, 
							  protocolInfo->iterations );
		zeroise( decodedValue, CRYPT_MAX_TEXTSIZE );
		}
	else
		{
		/* It's a standard password, use it as is */
		status = initMacInfo( protocolInfo->iMacContext,
							  passwordPtr->value, passwordPtr->valueLength,
							  protocolInfo->salt, protocolInfo->saltSize,
							  protocolInfo->iterations );
		}
	return( status );
	}

/****************************************************************************
*																			*
*								Init/Shutdown Functions						*
*																			*
****************************************************************************/

/* Prepare a CMP session */

static int clientStartup( SESSION_INFO *sessionInfoPtr )
	{
	const PROTOCOL_INFO *protocolInfoPtr = sessionInfoPtr->protocolInfo;
	CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
	NET_CONNECT_INFO connectInfo;
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* Make sure that we have all the needed information.  Plug-and-play PKI 
	   uses PKIBoot to get the CA cert and generates the requests internally, 
	   so we only need to check for these values if we're doing standard 
	   CMP.  The check for user ID and authentication information has
	   already been done at the general session level */
	if( !( cmpInfo->flags & CMP_PFLAG_PNPPKI ) )
		{
		if( cmpInfo->requestType == CRYPT_REQUESTTYPE_NONE )
			{
			setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_REQUESTTYPE,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}
		if( sessionInfoPtr->iAuthInContext == CRYPT_ERROR )
			{
			setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CACERTIFICATE,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}
		if( cmpInfo->requestType != CRYPT_REQUESTTYPE_PKIBOOT && \
			sessionInfoPtr->iCertRequest == CRYPT_ERROR )
			{
			setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}
		}

/*-----------------------------------------------------------------------*/
#ifdef SKIP_IO
goto skipIO;
#endif /* SKIP_IO */
/*-----------------------------------------------------------------------*/
	/* Connect to the remote server */
	initSessionNetConnectInfo( sessionInfoPtr, &connectInfo );
	if( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT )
		status = sNetConnect( &sessionInfoPtr->stream, STREAM_PROTOCOL_HTTP, 
							  &connectInfo, &sessionInfoPtr->errorInfo );
	else
		{
		const ALTPROTOCOL_INFO *altProtocolInfoPtr = \
									protocolInfoPtr->altProtocolInfo;

		assert( sessionInfoPtr->flags & SESSION_USEALTTRANSPORT );

		/* If we're using the HTTP port for a session-specific protocol, 
		   change it to the default port for the session-specific protocol 
		   instead */
		if( connectInfo.port == 80 )
			connectInfo.port = altProtocolInfoPtr->port;
		status = sNetConnect( &sessionInfoPtr->stream, 
							  altProtocolInfoPtr->type, 
							  &connectInfo, &sessionInfoPtr->errorInfo );
		}
	return( status );
	}

/* Shut down a CMP session */

static void shutdownFunction( SESSION_INFO *sessionInfoPtr )
	{
	CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* Clean up CMP-specific objects */
	if( cmpInfo->userInfo != CRYPT_ERROR )
		krnlSendNotifier( cmpInfo->userInfo, IMESSAGE_DECREFCOUNT );
	if( cmpInfo->savedMacContext != CRYPT_ERROR )
		krnlSendNotifier( cmpInfo->savedMacContext, IMESSAGE_DECREFCOUNT );

	sNetDisconnect( &sessionInfoPtr->stream );
	}

/* Exchange data with a CMP client/server.  Since the plug-and-play PKI 
   client performs multiple transactions, we wrap the basic clientTransact() 
   in an external function that either calls it indirectly when required 
   from the PnP code or just passes the call through to the transaction 
   function */

static int clientTransact( SESSION_INFO *sessionInfoPtr )
	{
	CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
	CMP_PROTOCOL_INFO protocolInfo;
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* Check that everything we need is present.  If it's a general CMP 
	   session this will already have been checked in clientStartup(), but
	   if it's coming from the PnPPKI wrapper it doesn't go through the
	   startup checks each time so we double-check here.  Since any problem
	   is just a one-off programming error, we only need a debug assertion
	   rather than a hardcoded check */
	assert( cmpInfo->requestType != CRYPT_REQUESTTYPE_NONE );
	assert( cmpInfo->requestType == CRYPT_REQUESTTYPE_PKIBOOT || \
			sessionInfoPtr->iCertRequest != CRYPT_ERROR );
	assert( cmpInfo->requestType == CRYPT_REQUESTTYPE_PKIBOOT || \
			sessionInfoPtr->iAuthInContext != CRYPT_ERROR );

	/* Initialise the client-side protocol state info */
	initProtocolInfo( &protocolInfo, 
					  sessionInfoPtr->flags & SESSION_ISCRYPTLIB );
	status = initClientInfo( sessionInfoPtr, &protocolInfo );
	if( cryptStatusError( status ) )
		{
		destroyProtocolInfo( &protocolInfo );
		return( status );
		}

	/* Write the message into the session buffer and send it to the server */
	status = writePkiMessage( sessionInfoPtr, &protocolInfo, 
							  ( cmpInfo->requestType == \
									CRYPT_REQUESTTYPE_PKIBOOT ) ? \
							  CMPBODY_GENMSG : CMPBODY_NORMAL );
	if( cryptStatusOK( status ) )
		{
		DEBUG_DUMP_CMP( protocolInfo.operation, 1, sessionInfoPtr );
		if( ( protocolInfo.operation == CTAG_PB_GENM || \
			  protocolInfo.operation == CTAG_PB_RR ) && \
			!( sessionInfoPtr->protocolFlags & CMP_PFLAG_RETAINCONNECTION ) )
			{
			/* There's no confirmation handshake for PKIBoot or a revocation 
			   request so we mark this as the last message if required */
			sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, NULL,
					TRUE );
			}
		status = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
								   CMP_CONTENT_TYPE_LEN );
		}
	if( cryptStatusError( status ) )
		{
		destroyProtocolInfo( &protocolInfo );
		return( status );
		}

	/* Read the server response */
	status = readPkiDatagram( sessionInfoPtr );
	if( cryptStatusOK( status ) )
		{
		const int responseType = reqToResp( protocolInfo.operation );

		DEBUG_DUMP_CMP( protocolInfo.operation, 2, sessionInfoPtr );
		if( cryptStatusError( responseType ) )
			status = responseType;
		else
			{
			status = readPkiMessage( sessionInfoPtr, &protocolInfo, 
									 responseType );
			}
		}
	if( cryptStatusOK( status ) && protocolInfo.operation == CTAG_PB_GENM )
		{
		/* It's a PKIBoot, add the trusted certs.  If the user wants the 
		   setting made permanent, they need to flush the config to disk 
		   after the session has completed */
		status = krnlSendMessage( sessionInfoPtr->ownerHandle,
								  IMESSAGE_SETATTRIBUTE, 
								  &sessionInfoPtr->iCertResponse,
								  CRYPT_IATTRIBUTE_CTL );
		if( status == CRYPT_ERROR_INITED )
			{
			/* If the certs are already present, trying to add them again
			   isn't an error */
			status = CRYPT_OK;
			}
		}
	if( cryptStatusError( status ) )
		{
		destroyProtocolInfo( &protocolInfo );
		return( status );
		}

	/* If it's a transaction type that doesn't need a confirmation, we're 
	   done */
	if( protocolInfo.operation == CTAG_PB_GENM || \
		protocolInfo.operation == CTAG_PB_RR )
		{
		if( protocolInfo.iMacContext != CRYPT_ERROR )
			{
			/* Remember the authentication context in case we can reuse it 
			   for another transaction */
			cmpInfo->savedMacContext = protocolInfo.iMacContext;
			protocolInfo.iMacContext = CRYPT_ERROR;
			}
		destroyProtocolInfo( &protocolInfo );
		return( CRYPT_OK );
		}

	/* Exchange confirmation data with the server */
	if( !( sessionInfoPtr->protocolFlags & CMP_PFLAG_RETAINCONNECTION ) )
		sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, NULL, 
				TRUE );
	status = writePkiMessage( sessionInfoPtr, &protocolInfo,
							  CMPBODY_CONFIRMATION );
	if( cryptStatusOK( status ) )
		{
		DEBUG_DUMP_CMP( protocolInfo.operation, 3, sessionInfoPtr );
		status = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
								   CMP_CONTENT_TYPE_LEN );
		}
	if( cryptStatusOK( status ) )
		status = readPkiDatagram( sessionInfoPtr );
	if( cryptStatusOK( status ) )
		{
		DEBUG_DUMP_CMP( protocolInfo.operation, 4, sessionInfoPtr );
		status = readPkiMessage( sessionInfoPtr, &protocolInfo, CTAG_PB_PKICONF );
		}
	if( cryptStatusOK( status ) && protocolInfo.iMacContext != CRYPT_ERROR )
		{
		/* Remember the authentication context in case we can reuse it for 
		   another transaction */
		cmpInfo->savedMacContext = protocolInfo.iMacContext;
		protocolInfo.iMacContext = CRYPT_ERROR;
		}
	destroyProtocolInfo( &protocolInfo );
	return( status );
	}

static int clientTransactWrapper( SESSION_INFO *sessionInfoPtr )
	{
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* If it's not a plug-and-play PKI session, just pass the call on down
	   to the client transaction function */
	if( !( sessionInfoPtr->sessionCMP->flags & CMP_PFLAG_PNPPKI ) )
		return( clientTransact( sessionInfoPtr ) );

	/* We're doing plug-and-play PKI, point the transaction function at the 
	   client-transact function to execute the PnP steps, then reset it back 
	   to the PnP wrapper after we're done */
	sessionInfoPtr->transactFunction = clientTransact;
	status = pnpPkiSession( sessionInfoPtr );
	sessionInfoPtr->transactFunction = clientTransactWrapper;

⌨️ 快捷键说明

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