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

📄 cmp.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Write the request body */
	writeConstructed( stream, objSize( msgData.length ),
					  protocolInfo->operation );
	writeSequence( stream, msgData.length );
	msgData.data = sMemBufPtr( stream );
	status = krnlSendMessage( sessionInfoPtr->iCertRequest,
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							  attrType );
	if( cryptStatusOK( status ) )
		status = sSkip( stream, msgData.length );

	return( status );
	}

static int writeResponseBody( STREAM *stream,
							  const SESSION_INFO *sessionInfoPtr,
							  const CMP_PROTOCOL_INFO *protocolInfo )
	{
	RESOURCE_DATA msgData;
	int payloadSize, status;

	UNUSED( protocolInfo );

	/* Find out how big the payload will be */
	if( protocolInfo->operation != CTAG_PB_RR )
		{
		setResourceData( &msgData, NULL, 0 );
		status = krnlSendMessage( sessionInfoPtr->iCertResponse,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_ENC_CERT );
		if( cryptStatusError( status ) )
			return( status );
		payloadSize = sizeofShortInteger( 0 ) + \
					  objSize( sizeofShortInteger( 0 ) ) + \
					  objSize( objSize( msgData.length ) );
		}
	else
		payloadSize = sizeofShortInteger( 0 );

	/* Write the response body wrapper */
	writeConstructed( stream, objSize( objSize( objSize( payloadSize ) ) ),
					  reqToRespType( 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 ) );
		}
	writeShortInteger( stream, PKISTATUS_OK, DEFAULT_TAG );
	if( protocolInfo->operation != CTAG_PB_RR )
		{
		writeSequence( stream, objSize( msgData.length ) );
		writeConstructed( stream, msgData.length, CTAG_CK_CERT );
		msgData.data = sMemBufPtr( stream );
		status = krnlSendMessage( sessionInfoPtr->iCertResponse,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_ENC_CERT );
		if( cryptStatusOK( status ) )
			status = sSkip( stream, msgData.length );
		}

	return( status );
	}

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 */
	setResourceData( &msgData, hashBuffer, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( sessionInfoPtr->iCertResponse,
						RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
						( protocolInfo->confHashAlgo == CRYPT_ALGO_SHA ) ? \
							CRYPT_CERTINFO_FINGERPRINT_SHA : \
							CRYPT_CERTINFO_FINGERPRINT_MD5 );
	if( cryptStatusError( status ) )
		return( status );
	length = ( int ) sizeofObject( 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 ) );
	}

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

	/* Write the error body */
	writeConstructed( stream, length, CTAG_PB_ERROR );
	return( writePkiStatusInfo( stream, protocolInfo->status,
								protocolInfo->pkiFailInfo ) );
	}

/* Read assorted PKI body messages */

static int readErrorBody( STREAM *stream, SESSION_INFO *sessionInfoPtr )
	{
	int endPos, length, status;

	/* Read the outer wrapper and PKI status info.  An error return status
	   is valid when we read the status info since we're reading an error
	   status and converting it into a cryptlib status, so we don't exit
	   unless it's a problem with the status info itself */
	readConstructed( stream, NULL, CTAG_PB_ERROR );
	readSequence( stream, &length );	/* Outer wrapper */
	endPos = stell( stream ) + length;
	status = readPkiStatusInfo( stream, &sessionInfoPtr->errorCode,
								sessionInfoPtr->errorMessage );
	if( status == CRYPT_ERROR_BADDATA || status == CRYPT_ERROR_UNDERFLOW )
		return( status );

	/* In addition to the PKI status info there can be another layer of
	   error information wrapped around it which is exactly the same only
	   different, so if we haven't got anything from the status info we
	   check to see whether this layer can give us anything */
	if( stell( stream ) < endPos && peekTag( stream ) == BER_INTEGER )
		{
		/* If there's an error code present and we haven't already set the
		   error code from the pkiStatusInfo, set it now */
		if( !sessionInfoPtr->errorCode )
			{
			long value;

			readShortInteger( stream, &value );
			sessionInfoPtr->errorCode = ( int ) value;
			}
		else
			readUniversal( stream );
		}
	if( stell( stream ) < endPos && peekTag( stream ) == BER_SEQUENCE && \
		!*sessionInfoPtr->errorMessage )
		/* Read the error text, ignoring any possible error status since the
		   overall error code from the status info is more meaningful than
		   a data format problem in trying to read the error text */
		readFreeText( stream, sessionInfoPtr->errorMessage,
					  MAX_ERRMSG_SIZE - 1 );

	return( status );
	}

/****************************************************************************
*																			*
*							PKI Header Functions							*
*																			*
****************************************************************************/

/* Write a PKI header from the session and protocol information:

	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 : sessionInfoPtr->iCertRequest;
	const CRYPT_HANDLE recipNameObject = \
			( sessionInfoPtr->flags & SESSION_ISSERVER ) ? \
			sessionInfoPtr->iCertResponse : sessionInfoPtr->iAuthInContext;
	STREAM nullStream;
	RESOURCE_DATA msgData;
	int senderNameLength, recipNameLength, protInfoLength, totalLength;
	int attributeLength = sizeofObject( \
								sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) +
								sizeofObject( 0 ) );
	int status;

	/* Determine how big the header data will be.  In theory we don't need
	   to send a recipient name for an ir but various implementations can't
	   handle a zero-length GeneralName so we supply it if it's available
	   even though it's redundant */
	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( senderNameObject,
						RESOURCE_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,
						RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
						CRYPT_IATTRIBUTE_SUBJECT );
			}
		}
	if( cryptStatusOK( status ) )
		{
		senderNameLength = msgData.length;
		setResourceData( &msgData, NULL, 0 );
		if( recipNameObject != CRYPT_ERROR )
			status = krnlSendMessage( recipNameObject,
						RESOURCE_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, in
			   which case 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;
	sMemOpen( &nullStream, NULL, 0 );
	if( protocolInfo->useMACsend )
		writeMacInfo( &nullStream, protocolInfo );
	else
		{
		writeContextAlgoID( &nullStream, sessionInfoPtr->privateKey,
							CRYPT_ALGO_SHA, ALGOID_FLAG_ALGOID_ONLY );
		attributeLength += writeCertID( NULL, sessionInfoPtr->privateKey );
		}
	protInfoLength = stell( &nullStream );
	sMemClose( &nullStream );
	totalLength = sizeofShortInteger( CMP_VERSION ) + \
				  objSize( senderNameLength ) + objSize( recipNameLength ) + \
				  objSize( protInfoLength ) + \
				  objSize( sizeofObject( protocolInfo->userIDsize ) ) + \
				  objSize( sizeofObject( protocolInfo->transIDsize ) ) + \
				  objSize( sizeofObject( protocolInfo->senderNonceSize ) ) + \
				  ( protocolInfo->recipNonceSize ? \
					objSize( sizeofObject( protocolInfo->recipNonceSize ) ) : 0 ) + \
				  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 recipient name information present).  We don't have
	   to worry about overflowing the stream when we get the names since
	   we've already done a length check */
	writeSequence( stream, totalLength );
	writeShortInteger( stream, CMP_VERSION, DEFAULT_TAG );
	writeConstructed( stream, senderNameLength, 4 );
	if( senderNameObject != CRYPT_ERROR )
		{
		setResourceData( &msgData, sMemBufPtr( stream ), senderNameLength );
		status = krnlSendMessage( senderNameObject,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_SUBJECT );
		if( cryptStatusError( status ) )
			return( status );
		sSkip( stream, senderNameLength );
		}
	else
		writeSequence( stream, 0 );
	writeConstructed( stream, recipNameLength, 4 );
	if( recipNameObject != CRYPT_ERROR )
		{
		setResourceData( &msgData, sMemBufPtr( stream ), recipNameLength );
		status = krnlSendMessage( recipNameObject,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_SUBJECT );
		if( cryptStatusError( status ) )
			return( status );
		sSkip( stream, recipNameLength );
		}
	else
		writeSequence( stream, 0 );

	/* Write the protection info, assorted nonces and ID's, and extra
	   information which the other side may be able to make use of */
	writeConstructed( stream, protInfoLength, CTAG_PH_PROTECTIONALGO );
	if( protocolInfo->useMACsend )
		writeMacInfo( stream, protocolInfo );
	else
		writeContextAlgoID( stream, sessionInfoPtr->privateKey,
							CRYPT_ALGO_SHA, ALGOID_FLAG_ALGOID_ONLY );
	writeConstructed( stream, objSize( protocolInfo->userIDsize ),
					  CTAG_PH_SENDERKID );
	writeOctetString( stream, protocolInfo->userID,
					  protocolInfo->userIDsize, DEFAULT_TAG );
	writeConstructed( stream, objSize( protocolInfo->transIDsize ),
					  CTAG_PH_TRANSACTIONID );
	writeOctetString( stream, protocolInfo->transID,
					  protocolInfo->transIDsize, DEFAULT_TAG );
	writeConstructed( stream, objSize( protocolInfo->senderNonceSize ),
					  CTAG_PH_SENDERNONCE );
	writeOctetString( stream, protocolInfo->senderNonce,
					  protocolInfo->senderNonceSize, DEFAULT_TAG );
	if( protocolInfo->recipNonceSize )
		{
		writeConstructed( stream, objSize( protocolInfo->recipNonceSize ),
						  CTAG_PH_RECIPNONCE );
		writeOctetString( stream, protocolInfo->recipNonce,
						  protocolInfo->recipNonceSize, DEFAULT_TAG );
		}
	writeConstructed( stream, objSize( attributeLength ),
					  CTAG_PH_GENERALINFO );
	writeSequence( stream, attributeLength );
	writeSequence( stream, sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
						   sizeofObject( 0 ) );
	writeOID( stream, OID_CRYPTLIB_PRESENCECHECK );
	status = writeSet( stream, 0 );
	if( !protocolInfo->useMACsend )
		status = writeCertID( stream, sessionInfoPtr->privateKey );

	return( status );

⌨️ 快捷键说明

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