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

📄 cmp_wr.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:

	UNUSED( protocolInfo );

	/* Find out how big the payload will be */
	if( protocolInfo->operation != CTAG_PB_RR )
		{
		/* If it's an encryption-only key we return the cert in encrypted
		   form.  The client performs POP by decrypting the returned cert */
		if( protocolInfo->cryptOnlyKey )
			{
			void *bufPtr = sMemBufPtr( stream ) + 100;
			int bufSize = sMemDataLeft( stream ) - 100;

			/* Extract the response data into the session buffer and wrap 
			   it in the standard format using the client's cert.  Since the 
			   client doesn't actually have the cert yet (only we have it, 
			   since it's only just been issued), we have to use the S/MIME 
			   v3 format (keys identified by key ID rather than 
			   issuerAndSerialNumber) because the client won't know its
			   iAndS until it decrypts the cert */
			setMessageData( &msgData, bufPtr, bufSize );
			status = krnlSendMessage( sessionInfoPtr->iCertResponse,
									  IMESSAGE_CRT_EXPORT, &msgData,
									  CRYPT_CERTFORMAT_CERTIFICATE );
			if( cryptStatusOK( status ) )
				status = envelopeWrap( bufPtr, msgData.length, 
									   bufPtr, &dataLength, bufSize,
									   CRYPT_FORMAT_CRYPTLIB, 
									   CRYPT_CONTENT_NONE, 
									   sessionInfoPtr->iCertResponse );
			if( cryptStatusError( status ) )
				return( status );
			}
		else
			{
			/* If it's a signature-capable key, return it in standard form */
			setMessageData( &msgData, NULL, 0 );
			status = krnlSendMessage( sessionInfoPtr->iCertResponse,
									  IMESSAGE_CRT_EXPORT, &msgData,
									  CRYPT_CERTFORMAT_CERTIFICATE );
			if( cryptStatusError( status ) )
				return( status );
			dataLength = msgData.length;
			}
		payloadSize += objSize( sizeofShortInteger( 0 ) ) + \
					   objSize( objSize( dataLength ) );
		}

	/* Write the response body wrapper */
	writeConstructed( stream, objSize( objSize( objSize( payloadSize ) ) ),
					  reqToResp( protocolInfo->operation ) );
	writeSequence( stream, objSize( objSize( payloadSize ) ) );

	/* Write the response.  We always write an OK status here because an
	   error will have been communicated by sending an explicit error
	   response */
	writeSequence( stream, objSize( payloadSize ) );
	writeSequence( stream, payloadSize );
	if( protocolInfo->operation != CTAG_PB_RR )
		{
		writeShortInteger( stream, 0, DEFAULT_TAG );
		writeSequence( stream, sizeofShortInteger( 0 ) );
		}
	status = writeShortInteger( stream, PKISTATUS_OK, DEFAULT_TAG );
	if( protocolInfo->operation == CTAG_PB_RR )
		/* If it's a revocation request, there's no data included in the
		   response */
		return( status );

	/* Write the cert data, either as a standard cert or as CMS encrypted 
	   data if the request was for an encryption-only cert */
	writeSequence( stream, objSize( dataLength ) );
	if( protocolInfo->cryptOnlyKey )
		{
		BYTE *bufPtr;

		assert( startPos + 100 - stell( stream ) > 0 );
		writeConstructed( stream, dataLength, CTAG_CK_NEWENCRYPTEDCERT );
		bufPtr = sMemBufPtr( stream );
		memmove( bufPtr, bufPtr + startPos + 100 - stell( stream ), 
				 dataLength );
		return( sSkip( stream, dataLength ) );
		}
	writeConstructed( stream, dataLength, CTAG_CK_CERT );
	return( exportCertToStream( stream, sessionInfoPtr->iCertResponse, 
								CRYPT_CERTFORMAT_CERTIFICATE ) );
	}

/* Write conf body */

static int writeConfBody( STREAM *stream,
						  const SESSION_INFO *sessionInfoPtr,
						  const CMP_PROTOCOL_INFO *protocolInfo )
	{
	RESOURCE_DATA msgData;
	BYTE hashBuffer[ CRYPT_MAX_HASHSIZE ];
	int length, status;

	/* Get the certificate hash */
	setMessageData( &msgData, hashBuffer, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( sessionInfoPtr->iCertResponse,
						IMESSAGE_GETATTRIBUTE_S, &msgData,
						( protocolInfo->confHashAlgo == CRYPT_ALGO_SHA ) ? \
							CRYPT_CERTINFO_FINGERPRINT_SHA : \
							CRYPT_CERTINFO_FINGERPRINT_MD5 );
	if( cryptStatusError( status ) )
		return( status );
	length = ( int ) objSize( msgData.length ) + sizeofShortInteger( 0 );

	/* Write the confirmation body */
	writeConstructed( stream, objSize( objSize( length ) ),
					  CTAG_PB_CERTCONF );
	writeSequence( stream, objSize( length ) );
	writeSequence( stream, length );
	writeOctetString( stream, hashBuffer, msgData.length, DEFAULT_TAG );
	return( writeShortInteger( stream, 0, DEFAULT_TAG ) );
	}

/* Write genMsg body */

static int writeGenMsgBody( STREAM *stream,
							SESSION_INFO *sessionInfoPtr,
							const CMP_PROTOCOL_INFO *protocolInfo )
	{
	CRYPT_CERTIFICATE iCTL;
	RESOURCE_DATA msgData;
	int status;

	UNUSED( protocolInfo );

	/* Get the CTL from the CA object.  We recreate this each time rather 
	   than cacheing it in the session to ensure that changes in the trusted
	   cert set while the session is active get reflected back to the 
	   caller.
	   
	   In addition to the explicitly trusted certs, we also include the CA 
	   cert(s) in the CTL as implicitly-trusted certs.  This is done both
	   because users often forget to mark them as trusted on the server and 
	   then wonder where their CA certs are on the client, and because these 
	   should inherently be trusted, since the user is about to get their 
	   certs issued by them */
	status = krnlSendMessage( sessionInfoPtr->ownerHandle,
							  IMESSAGE_GETATTRIBUTE, &iCTL,
							  CRYPT_IATTRIBUTE_CTL );
	if( cryptStatusError( status ) )
		return( status );
	status = krnlSendMessage( iCTL, IMESSAGE_SETATTRIBUTE,
							  ( void * ) &sessionInfoPtr->privateKey,
							  CRYPT_IATTRIBUTE_CERTCOLLECTION );
	if( cryptStatusError( status ) )
		return( status );
	setMessageData( &msgData, NULL, 0 );
	status = krnlSendMessage( iCTL, IMESSAGE_CRT_EXPORT, &msgData, 
							  CRYPT_CERTFORMAT_CERTCHAIN );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCTL, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Write the response body wrapper.  As with the cert ID, we can use the
	   imprecision of the ASN.1 that CMP is specified in to interpret the
	   InfoTypeAndValue:

		InfoTypeAndValue ::= SEQUENCE {
			infoType	OBJECT IDENTIFIER,
			infoValue	ANY DEFINED BY infoType OPTIONAL
			}

	   as:

		infoType ::= id-signedData
		infoValue ::= [0] EXPLICIT SignedData

	   which makes it standard CMS data that can be passed directly to the 
	   CMS code */
	writeConstructed( stream, objSize( msgData.length ), CTAG_PB_GENP );
	writeSequence( stream, msgData.length );
	status = exportCertToStream( stream, iCTL, CRYPT_CERTFORMAT_CERTCHAIN );
	krnlSendNotifier( iCTL, IMESSAGE_DECREFCOUNT );
	return( status );
	}

/* Write error body */

static int writeErrorBody( STREAM *stream,
						   const CMP_PROTOCOL_INFO *protocolInfo )
	{
	const int length = writePkiStatusInfo( NULL, protocolInfo->status,
										   protocolInfo->pkiFailInfo );

	/* Write the error body.  We don't write the error text string because
	   it reveals too much about the internal operation of the CA, some of 
	   which may aid an attacker */
	writeConstructed( stream, objSize( length ), CTAG_PB_ERROR );
	writeSequence( stream, length );
	return( writePkiStatusInfo( stream, protocolInfo->status,
								protocolInfo->pkiFailInfo ) );
	}

/****************************************************************************
*																			*
*								Write a PKI Header							*
*																			*
****************************************************************************/

/* Write a PKI header.  Fields marked with a * are redundant and are only 
   sent when we're not sending minimal headers.  Fields marked with a + are
   only sent in the first message or when not sending minimal headers:

	header				SEQUENCE {
		version			INTEGER (2),
	   *sender		[4]	EXPLICIT DirectoryName,	-- DN of initiator
	   *recipient	[4]	EXPLICIT DirectoryName,	-- DN of responder
		protAlgo	[1]	EXPLICIT AlgorithmIdentifier,
	   +protKeyID	[2] EXPLICIT OCTET STRING,
		transID		[4] EXPLICIT OCTET STRING SIZE (16),-- Random/copied from sender
	   *nonce		[5] EXPLICIT OCTET STRING SIZE (16),-- Random
	   *nonceX		[6] EXPLICIT OCTET STRING SIZE (n),	-- Copied from sender
		generalInfo	[8] EXPLICIT SEQUENCE OF Info OPT	-- cryptlib-specific info
		} */

static int writePkiHeader( STREAM *stream, SESSION_INFO *sessionInfoPtr,
						   CMP_PROTOCOL_INFO *protocolInfo )
	{
	CRYPT_HANDLE senderNameObject = \
			( sessionInfoPtr->flags & SESSION_ISSERVER ) ? \
				sessionInfoPtr->privateKey : \
			protocolInfo->cryptOnlyKey ? \
				sessionInfoPtr->iAuthOutContext : \
				sessionInfoPtr->iCertRequest;
	const CRYPT_HANDLE recipNameObject = \
			( sessionInfoPtr->flags & SESSION_ISSERVER ) ? \
			sessionInfoPtr->iCertResponse : sessionInfoPtr->iAuthInContext;
	STREAM nullStream;
	RESOURCE_DATA msgData;
#ifdef USE_FULL_HEADERS
	const BOOLEAN useFullHeader = TRUE;
#else
	const BOOLEAN useFullHeader = !( protocolInfo->isCryptlib || \
									 protocolInfo->operation == CTAG_PB_GENM );
			/* Send a minimal header if the other side is cryptlib or if 
			   we're doing PKIBoot, for which we couldn't send full headers 
			   if we wanted to */
#endif /* USE_MINIMAL_HEADERS */
	BOOLEAN sendClibID = FALSE, sendCertID = FALSE;
	int senderNameLength = 0, recipNameLength = 0, attributeLength = 0;
	int protInfoLength, totalLength, status;

	assert( !useFullHeader || protocolInfo->userIDsize > 0 );

	krnlSendMessage( sessionInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE, 
					 &protocolInfo->hashAlgo, CRYPT_OPTION_ENCR_HASH );

	/* 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 && \
			!( sessionInfoPtr->flags & SESSION_ISSERVER ) && \
			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;
		}

	/* Determine how big the remaining header data will be */
	sMemOpen( &nullStream, NULL, 0 );
	if( protocolInfo->useMACsend )
		writeMacInfo( &nullStream, protocolInfo, 

⌨️ 快捷键说明

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