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

📄 cmp.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
						   CMP_PROTOCOL_INFO *protocolInfo )
	{
	MESSAGE_KEYMGMT_INFO getkeyInfo;
	int status;

	/* Set up general authentication information and if there's client auth. 
	   info still present from a previous transaction that used MAC
	   authentication, clear it */
	status = setProtocolInfo( protocolInfo, NULL, 0, 0 );
	if( cryptStatusError( status ) )
		return( status );
	if( sessionInfoPtr->cmpUserInfo != CRYPT_ERROR )
		{
		krnlSendNotifier( sessionInfoPtr->cmpUserInfo, 
						  IMESSAGE_DECREFCOUNT );
		sessionInfoPtr->cmpUserInfo = CRYPT_ERROR;
		}

	/* Get the user info for the user that originally authorised the issue
	   of the cert that signed the request.  This serves two purposes, it 
	   obtains the user ID if it wasn't supplied in the request (for example 
	   if the request uses only a cert ID), and it verifies that the 
	   authorising cert belongs to a valid user */
	setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,
						   protocolInfo->certID, protocolInfo->certIDsize, 
						   NULL, 0, KEYMGMT_FLAG_GETISSUER );
	status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
							  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
							  KEYMGMT_ITEM_PKIUSER );
	if( cryptStatusError( status ) )
		{
		protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
		retExt( sessionInfoPtr, status, 
				"Couldn't find PKI user information for owner of requesting "
				"cert" );
		}
	if( !( sessionInfoPtr->flags & SESSION_ISENCODEDUSERID ) )
		{
		RESOURCE_DATA msgData;

		/* There's currently no user ID present (or if it's present it's a
		   non-userID value such as a cert ID), replace it with the PKI user 
		   ID */
		setMessageData( &msgData, sessionInfoPtr->userName, 
						CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( getkeyInfo.cryptHandle,
								  IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_CERTINFO_PKIUSER_ID );
		if( cryptStatusError( status ) )
			retExt( sessionInfoPtr, status, 
					"Couldn't read PKI user data from PKI user object" );
		sessionInfoPtr->userNameLength = msgData.length;
		sessionInfoPtr->flags |= SESSION_ISENCODEDUSERID;
		}
	krnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );

	/* Get the public key identified by the cert ID from the cert store.  
	   This assumes that the owner of an existing cert/existing user is 
	   authorised to request further certs using the existing one.  If we 
	   get a not found error we report it as "signer not trusted", which 
	   can also mean "signer unknown" */
	setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,
						   protocolInfo->certID, protocolInfo->certIDsize, 
						   NULL, 0, KEYMGMT_FLAG_USAGE_SIGN );
	status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
							  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
							  KEYMGMT_ITEM_PUBLICKEY );
	if( cryptStatusError( status ) )
		{
		protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
		retExt( sessionInfoPtr, status, 
				"Couldn't find certificate for requested user" );
		}
	sessionInfoPtr->iAuthInContext = getkeyInfo.cryptHandle;
	protocolInfo->userIDchanged = FALSE;

	return( CRYPT_OK );
	}

/* Hash/MAC the message header and body */

int hashMessageContents( const CRYPT_CONTEXT iHashContext,
						 const void *data, const int length )
	{
	STREAM stream;
	BYTE buffer[ 8 ];

	/* Delete the hash/MAC value, which resets the context */
	krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL, 
					 CRYPT_CTXINFO_HASHVALUE );

	/* Write the pseudoheader used for hashing/MACing the header and body and
	   hash/MAC it */
	sMemOpen( &stream, buffer, 8 );
	writeSequence( &stream, length );
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 
					 stell( &stream ) );
	sMemClose( &stream );
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, ( void * ) data, 
					 length );
	return( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 0 ) );
	}

/* Deliver an Einladung betreff Kehrseite to the client.  We don't bother
   checking the return value since there's nothing that we can do in the 
   case of an error except close the connection, which we do anyway since 
   this is the last message */

static void sendErrorResponse( SESSION_INFO *sessionInfoPtr,
							   CMP_PROTOCOL_INFO *protocolInfo,
							   const int status )
	{
	/* If we were going to protect the communication with the client with a
	   MAC and something failed, make sure that we don't try and MAC the
	   response since the failure could be a client MAC failure, failure to
	   locate the MAC key, etc etc */
	protocolInfo->useMACsend = FALSE;
	protocolInfo->status = status;
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, NULL, TRUE );
	writePkiMessage( sessionInfoPtr, protocolInfo, CMPBODY_ERROR );
	DEBUG_DUMP_CMP( CTAG_PB_ERROR, 1, sessionInfoPtr );
	writePkiDatagram( sessionInfoPtr );
	}

/* Set up information needed to perform a client-side transaction */

static int initClientInfo( SESSION_INFO *sessionInfoPtr,
						   CMP_PROTOCOL_INFO *protocolInfo )
	{
	int status;

	assert( !( sessionInfoPtr->flags & SESSION_ISSERVER ) );

	/* Determine what we need to do based on the request type */
	protocolInfo->operation = clibReqToReq( sessionInfoPtr->cmpRequestType );

	/* If we're using public key-based authentication, set up the key and 
	   user ID information */
	if( sessionInfoPtr->cmpRequestType != CRYPT_REQUESTTYPE_PKIBOOT && \
		sessionInfoPtr->cmpRequestType != CRYPT_REQUESTTYPE_INITIALISATION && \
		!( sessionInfoPtr->cmpRequestType == CRYPT_REQUESTTYPE_REVOCATION && \
		   sessionInfoPtr->passwordLength > 0 ) )
		{
		/* If it's an encryption-only key, remember this for later when we 
		   need to authenticate our request messages */
		status = krnlSendMessage( sessionInfoPtr->privateKey, IMESSAGE_CHECK, 
								  NULL, MESSAGE_CHECK_PKC_SIGN );
		if( cryptStatusError( status ) )
			{
			/* The private key can't be used for signature creation, use
			   the alternate authentication key instead */
			protocolInfo->authContext = sessionInfoPtr->iAuthOutContext;
			protocolInfo->cryptOnlyKey = TRUE;
			}
		else
			/* The private key that we're using is capable of authenticating 
			   requests */
			protocolInfo->authContext = sessionInfoPtr->privateKey;

		/* If we're not talking to a cryptlib peer, get the user ID.  If 
		   it's a standard signed request the authenticating object will be 
		   the private key, however if the private key is an encryption-only 
		   key the message authentication key is a separate object.  To 
		   handle this we get the user ID from the signing key rather than 
		   automatically using the private key */
		if( !protocolInfo->isCryptlib )
			{
			RESOURCE_DATA msgData;
			BYTE userID[ CRYPT_MAX_HASHSIZE ];

			setMessageData( &msgData, userID, CRYPT_MAX_HASHSIZE );
			status = krnlSendMessage( protocolInfo->authContext, 
									  IMESSAGE_GETATTRIBUTE_S, &msgData, 
									  CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
			if( cryptStatusOK( status ) )
				status = setProtocolInfo( protocolInfo, userID, 
										  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( sessionInfoPtr->cmpSavedMacContext != CRYPT_ERROR )
		{
		setProtocolInfo( protocolInfo, NULL, 0, PROTOCOLINFO_SET_TRANSID );
		protocolInfo->useMACsend = protocolInfo->useMACreceive = TRUE;
		protocolInfo->iMacContext = sessionInfoPtr->cmpSavedMacContext;
		sessionInfoPtr->cmpSavedMacContext = CRYPT_ERROR;
		return( CRYPT_OK );
		}

	/* We're using MAC authentication, initialise the protocol info */
	if( sessionInfoPtr->flags & SESSION_ISENCODEDUSERID )
		{
		BYTE decodedValue[ CRYPT_MAX_TEXTSIZE ];
		int decodedValueLength;

		/* It's a cryptlib-style encoded user ID, decode it into its binary 
		   value */
		decodedValueLength = decodePKIUserValue( decodedValue,
										sessionInfoPtr->userName,
										sessionInfoPtr->userNameLength );
		if( cryptStatusError( decodedValueLength ) )
			{
			assert( NOTREACHED );
			retExt( sessionInfoPtr, decodedValueLength, 
					"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, sessionInfoPtr->userName,
								  sessionInfoPtr->userNameLength, 
								  PROTOCOLINFO_SET_ALL );
	if( cryptStatusError( status ) )
		return( status );

	/* Set up the MAC context used to authenticate messages */
	if( sessionInfoPtr->flags & SESSION_ISENCODEDPW )
		{
		BYTE decodedValue[ CRYPT_MAX_TEXTSIZE ];
		int decodedValueLength;

		/* It's a cryptlib-style encoded password, decode it into its binary 
		   value */
		decodedValueLength = decodePKIUserValue( decodedValue,
											sessionInfoPtr->password,
											sessionInfoPtr->passwordLength );
		if( cryptStatusError( decodedValueLength ) )
			{
			assert( NOTREACHED );
			retExt( sessionInfoPtr, decodedValueLength, 
					"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,
							  sessionInfoPtr->password, 
							  sessionInfoPtr->passwordLength,
							  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;
	NET_CONNECT_INFO connectInfo;
	int status;

	/* 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( !( sessionInfoPtr->flags & SESSION_ISPNPPKI ) )
		{
		if( sessionInfoPtr->cmpRequestType == 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( sessionInfoPtr->cmpRequestType != 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_TRANSACTION, 
							  &connectInfo, sessionInfoPtr->errorMessage, 
							  &sessionInfoPtr->errorCode );
	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->errorMessage, 
							  &sessionInfoPtr->errorCode );
		}
	if( cryptStatusError( status ) )
		return( status );
	if( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT )
		sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_CONTENTTYPE,
				( void * ) protocolInfoPtr->clientContentType, 
				strlen( protocolInfoPtr->clientContentType ) );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_HANDSHAKETIMEOUT, NULL, 0 );
	return( CRYPT_OK );
	}

/* Shut down a CMP session */

static void shutdownFunction( SESSION_INFO *sessionInfoPtr )
	{
	/* Clean up CMP-specific objects */
	if( sessionInfoPtr->cmpUserInfo != CRYPT_ERROR )
		krnlSendNotifier( sessionInfoPtr->cmpUserInfo,
						  IMESSAGE_DECREFCOUNT );
	if( sessionInfoPtr->cmpSavedMacContext != CRYPT_ERROR )
		krnlSendNotifier( sessionInfoPtr->cmpSavedMacContext,
						  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_PROTOCOL_INFO protocolInfo;
	int status;

	/* 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 */

⌨️ 快捷键说明

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