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

📄 cryptenv.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
		if( cryptStatusOK( status ) )
			return( attributeCopy( messageDataPtr, getkeyInfo.auxInfo,
								   getkeyInfo.auxInfoLength ) );
		return( status );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

static int processSetAttribute( ENVELOPE_INFO *envelopeInfoPtr,
								void *messageDataPtr, const int messageValue )
	{
	MESSAGE_CHECK_TYPE checkType = MESSAGE_CHECK_NONE;
	ACTION_TYPE usage = ACTION_NONE;
	static const struct {
		const CRYPT_ATTRIBUTE_TYPE type;	/* Attribute type */
		const ACTION_TYPE usage;			/* Corresponding usage type */
		const MESSAGE_CHECK_TYPE checkType;	/*  and check type */
		} checkTable[] = {
#ifdef USE_COMPRESSION
		{ CRYPT_ENVINFO_COMPRESSION, ACTION_COMPRESS, MESSAGE_CHECK_NONE },
#endif /* USE_COMPRESSION */
		{ CRYPT_ENVINFO_MAC, ACTION_MAC, MESSAGE_CHECK_MAC },
		{ CRYPT_ENVINFO_KEY, ACTION_CRYPT, MESSAGE_CHECK_CRYPT },
		{ CRYPT_ENVINFO_PUBLICKEY, ACTION_CRYPT, MESSAGE_CHECK_PKC_ENCRYPT },
		{ CRYPT_ENVINFO_PRIVATEKEY, ACTION_CRYPT, MESSAGE_CHECK_PKC_DECRYPT },
		{ CRYPT_ENVINFO_HASH, ACTION_SIGN, MESSAGE_CHECK_HASH },
		{ CRYPT_ENVINFO_TIMESTAMP_AUTHORITY, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_ENVINFO_DETACHEDSIGNATURE, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_IATTRIBUTE_INCLUDESIGCERT, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_IATTRIBUTE_ATTRONLY, ACTION_SIGN, MESSAGE_CHECK_NONE },
		{ CRYPT_ATTRIBUTE_NONE, ACTION_NONE }
		};
	const int value = *( int * ) messageDataPtr;
	int i, status;

	/* If it's an initialisation message, there's nothing to do */
	if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
		return( CRYPT_OK );

	/* Generic attributes are valid for all envelope types */
	if( messageValue == CRYPT_ATTRIBUTE_BUFFERSIZE )
		{
		envelopeInfoPtr->bufSize = value;
		return( CRYPT_OK );
		}

	/* If it's meta-information, process it now */
	if( messageValue == CRYPT_ENVINFO_CURRENT_COMPONENT )
		return( moveCursor( envelopeInfoPtr, value ) );

	/* In general we can't add new enveloping information once we've started
	   processing data */
	if( messageValue != CRYPT_ENVINFO_CURRENT_COMPONENT && \
		envelopeInfoPtr->state != STATE_PREDATA )
		{
		/* We can't add new information once we've started enveloping */
		if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
			return( CRYPT_ERROR_INITED );

		/* We can only add signature check information once we've started
		   de-enveloping */
		if( messageValue != CRYPT_ENVINFO_SIGNATURE )
			return( CRYPT_ERROR_INITED );
		}

	/* If we're de-enveloping PGP data, make sure that the attribute is 
	   valid for PGP envelopes.  We can't perform this check via the ACLs 
	   because the data type isn't known at envelope creation time, so 
	   there's a single generic de-envelope type for which the ACLs allow 
	   the union of all de-enveloping attribute types.  The following check 
	   weeds out the ones that don't work for PGP */
	if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
		{
		if( messageValue == CRYPT_OPTION_ENCR_MAC || \
			messageValue == CRYPT_ENVINFO_MAC || \
			messageValue == CRYPT_ENVINFO_KEY || \
			messageValue == CRYPT_ENVINFO_SESSIONKEY )
			return( CRYPT_ARGERROR_VALUE );
		if( messageValue == CRYPT_ENVINFO_HASH && \
			!( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) )
			/* We can add a hash if we're creating a detached signature */
			return( CRYPT_ARGERROR_VALUE );
		}

	/* Since the information may not be used for quite some time after it's
	   added, we do some preliminary checking here to allow us to return an
	   error code immediately rather than from some deeply-buried function an
	   indeterminate time in the future.  Since much of the checking is
	   similar, we use a table-driven check for most types and fall back to
	   custom checking for special cases */
	for( i = 0; checkTable[ i ].type != ACTION_NONE; i++ )
		if( checkTable[ i ].type == messageValue )
			{
			if( envelopeInfoPtr->usage != ACTION_NONE && \
				envelopeInfoPtr->usage != checkTable[ i ].usage )
				return( exitErrorInited( envelopeInfoPtr, messageValue ) );
			usage = checkTable[ i ].usage;
			checkType = checkTable[ i ].checkType;
			break;
			}
	if( usage == ACTION_NONE )
		switch( messageValue )
			{
			case CRYPT_OPTION_ENCR_ALGO:
				if( cryptStatusError( \
						envelopeInfoPtr->checkCryptAlgo( value, 
								isStreamCipher( value ) ? CRYPT_MODE_OFB : \
								( envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) ? \
								CRYPT_MODE_CFB : CRYPT_MODE_CBC ) ) )
					return( CRYPT_ARGERROR_VALUE );
				envelopeInfoPtr->defaultAlgo = value;
				return( CRYPT_OK );

			case CRYPT_OPTION_ENCR_HASH:
				if( cryptStatusError( \
						envelopeInfoPtr->checkHashAlgo( value ) ) )
					return( CRYPT_ARGERROR_VALUE );
				envelopeInfoPtr->defaultHash = value;
				return( CRYPT_OK );

			case CRYPT_OPTION_ENCR_MAC:
				if( cryptStatusError( \
						envelopeInfoPtr->checkHashAlgo( value ) ) )
					return( CRYPT_ARGERROR_VALUE );
				envelopeInfoPtr->defaultMAC = value;
				return( CRYPT_OK );

			case CRYPT_ENVINFO_DATASIZE:
				if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_DATASIZE ) );
				break;

			case CRYPT_ENVINFO_CONTENTTYPE:
				/* Exactly what is supposed to happen when PGP is asked to 
				   sign non-plain-data is ill-defined.  No command-line PGP 
				   option will generate this type of message, and the RFCs 
				   don't specify the behaviour (in fact RFC 1991's 
				   description of PGP signing is completely wrong).  In 
				   practice PGP hashes and signs the payload contents of a 
				   PGP literal data packet, however if there are extra layers 
				   of processing between the signing and literal packets (eg 
				   compression or encryption), what gets hashed isn't 
				   specified.  If it's always the payload of the final 
				   (literal) data packet, we'd have to be able to burrow down 
				   through arbitrary amounts of further data and processing 
				   in order to get to the payload data to hash (this also 
				   makes things like mail gateways that only allow signed 
				   messages through infeasible unless the gateway holds 
				   everyone's private key in order to get at the plaintext to 
				   hash).  Because of this problem, we disallow any attempts 
				   to set a content-type other than plain data if we're 
				   signing a PGP-format message */
				if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
					envelopeInfoPtr->usage == ACTION_SIGN && \
					value != CRYPT_CONTENT_DATA )
					return( CRYPT_ARGERROR_VALUE );

				/* For user-friendliness we allow overwriting a given content
				   type with the same type, which is useful for cases when
				   cryptlib automatically presets the type based on other
				   information */
				if( envelopeInfoPtr->contentType && \
					envelopeInfoPtr->contentType != value )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_CONTENTTYPE ) );
				break;

			case CRYPT_ENVINFO_SESSIONKEY:
				checkType = MESSAGE_CHECK_CRYPT;
				if( envelopeInfoPtr->usage != ACTION_NONE && \
					!( ( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
					   envelopeInfoPtr->usage == ACTION_CRYPT ) )
					/* On de-enveloping the usage is set by the enveloped data
					   format, so setting a session key when the usage is
					   already set to encryption isn't an error */
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_SESSIONKEY ) );
				usage = ACTION_CRYPT;
				break;

			case CRYPT_ENVINFO_SIGNATURE:
				checkType = \
					( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) ? \
						MESSAGE_CHECK_PKC_SIGCHECK : MESSAGE_CHECK_PKC_SIGN;
				if( envelopeInfoPtr->usage != ACTION_NONE && \
					envelopeInfoPtr->usage != ACTION_SIGN )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_SIGNATURE ) );
				if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
					envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA )
					/* See the long comment for CRYPT_ENVINFO_CONTENTTYPE */
					return( CRYPT_ARGERROR_VALUE );
				usage = ACTION_SIGN;
				break;

			case CRYPT_ENVINFO_SIGNATURE_EXTRADATA:
				if( envelopeInfoPtr->type != CRYPT_FORMAT_CMS && \
					envelopeInfoPtr->type != CRYPT_FORMAT_SMIME )
					return( CRYPT_ARGERROR_VALUE );
				if( envelopeInfoPtr->usage != ACTION_NONE && \
					envelopeInfoPtr->usage != ACTION_SIGN )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) );
				break;

			case CRYPT_ENVINFO_ORIGINATOR:
				checkType = MESSAGE_CHECK_PKC_KA_EXPORT;
				if( envelopeInfoPtr->usage != ACTION_NONE && \
					envelopeInfoPtr->usage != ACTION_CRYPT )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_ORIGINATOR ) );
				usage = ACTION_CRYPT;
				if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_ORIGINATOR ) );
				break;

			case CRYPT_ENVINFO_KEYSET_ENCRYPT:
				checkType = MESSAGE_CHECK_PKC_ENCRYPT;
				if( envelopeInfoPtr->iEncryptionKeyset != CRYPT_ERROR )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_KEYSET_ENCRYPT ) );
				break;

			case CRYPT_ENVINFO_KEYSET_DECRYPT:
				checkType = MESSAGE_CHECK_PKC_DECRYPT;
				if( envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_KEYSET_DECRYPT ) );
				break;

			case CRYPT_ENVINFO_KEYSET_SIGCHECK:
				checkType = MESSAGE_CHECK_PKC_SIGCHECK;
				if( envelopeInfoPtr->iSigCheckKeyset != CRYPT_ERROR )
					return( exitErrorInited( envelopeInfoPtr, 
											 CRYPT_ENVINFO_KEYSET_SIGCHECK ) );
				break;

			default:
				assert( NOTREACHED );
			}
	if( checkType != MESSAGE_CHECK_NONE )
		{
		/* Check the object as appropriate.  A key agreement key can also act
		   as a public key because of the way KEA works, so if a check for a
		   straight public key fails we try again to see if it's a key
		   agreement key with import capabilities */
		status = krnlSendMessage( value, IMESSAGE_CHECK, NULL, checkType );
		if( status == CRYPT_ARGERROR_OBJECT && \
			messageValue == CRYPT_ENVINFO_PUBLICKEY )
			status = krnlSendMessage( value, IMESSAGE_CHECK, NULL,
									  MESSAGE_CHECK_PKC_KA_IMPORT );
		if( cryptStatusError( status ) )
			return( CRYPT_ARGERROR_NUM1 );

		/* Make sure that the object corresponds to a representable algorithm
		   type.  Note that this check isn't totally foolproof on de-
		   enveloping PGP data since the user can push the hash context 
		   before they push the signed data (to signifiy the use of a 
		   detached signature) so that it's checked using the default 
		   (CMS) algorithm values rather then PGP ones */
		if( checkType == MESSAGE_CHECK_CRYPT || \
			checkType == MESSAGE_CHECK_HASH || \
			checkType == MESSAGE_CHECK_MAC )
			{
			CRYPT_ALGO_TYPE algorithm;

			krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, &algorithm,
							 CRYPT_CTXINFO_ALGO );
			if( checkType == MESSAGE_CHECK_CRYPT )
				{
				CRYPT_MODE_TYPE mode;

				krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, &mode,
								 CRYPT_CTXINFO_MODE );
				status = envelopeInfoPtr->checkCryptAlgo( algorithm, mode );
				}
			else
				status = envelopeInfoPtr->checkHashAlgo( algorithm );
			if( cryptStatusError( status ) )
				return( CRYPT_ERROR_NOTAVAIL );
			}

		/* If we're using CMS enveloping, the object must have an initialised 
		   cert of the correct type associated with it.  Most of this will be 
		   caught by the kernel, but there are a couple of special cases (eg 
		   attribute cert where the main object is a PKC context) which are 
		   missed by the general kernel checks */
		if( ( messageValue == CRYPT_ENVINFO_SIGNATURE || \
			  messageValue == CRYPT_ENVINFO_PUBLICKEY || \
			  messageValue == CRYPT_ENVINFO_PRIVATEKEY || \
			  messageValue == CRYPT_ENVINFO_ORIGINATOR ) && 
			( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \
			  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) )
			{
			int inited, certType;

			status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, &inited, 
									  CRYPT_CERTINFO_IMMUTABLE );
			if( cryptStatusError( status ) || !inited )
				return( CRYPT_ARGERROR_NUM1 );
			status = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,
									  &certType, CRYPT_CERTINFO_CERTTYPE );
			if( cryptStatusError( status ) ||
				( certType != CRYPT_CERTTYPE_CERTIFICATE && \
				  certType != CRYPT_CERTTYPE_CERTCHAIN ) )
				return( CRYPT_ARGERROR_NUM1 );
			}
		}

	/* Add it to the envelope */
	status = envelopeInfoPtr->addInfo( envelopeInfoPtr, messageValue,
									   &value, 0 );
	if( cryptStatusError( status ) )
		{
		if( status == CRYPT_ERROR_INITED )
			return( exitErrorInited( envelopeInfoPtr, messageValue ) );
		return( status );
		}
	if( usage != ACTION_NONE )
		/* The action was successfully added, update the usage if 
		   necessary */
		envelopeInfoPtr->usage = usage;
	return( CRYPT_OK );
	}

static int processSetAttributeS( ENVELOPE_INFO *envelopeInfoPtr,
								 void *messageDataPtr, const int messageValue )
	{
	RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
	ACTION_TYPE usage = ACTION_NONE;
	int status;

	/* Handle the various information types */
	switch( messageValue )
		{
		case CRYPT_ENVINFO_PASSWORD:
			/* Set the envelope usage type based on the fact that we've been
			   fed a password */
			if( envelopeInfoPtr->usage == ACTION_NONE )

⌨️ 快捷键说明

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