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

📄 crypt.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
			krnlSendNotifier( *iDestContext, RESOURCE_IMESSAGE_DESTROY );
		}
	if( cryptStatusError( status ) )
		{
		*iDestContext = CRYPT_ERROR;
		return( status );
		}

	return( CRYPT_OK );
	}

/* Checks that a context meets the given requirements */

static int checkContext( CRYPT_INFO *cryptInfoPtr,
						 const RESOURCE_MESSAGE_CHECK_TYPE checkType )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
	const CRYPT_ALGO cryptAlgo = capabilityInfoPtr->cryptAlgo;
	int usageCount, status;

	/* Make sure that the object's usage count is still valid.  The usage 
	   count is a type of meta-capability which overrides all other 
	   capabilities in that an object with an expired usage count isn't
	   valid for anything no matter what the available capabilities are */
	status = krnlSendMessage( cryptInfoPtr->objectHandle, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &usageCount, CRYPT_PROPERTY_USAGECOUNT );
	if( cryptStatusError( status ) || \
		( usageCount != CRYPT_UNUSED && usageCount <= 0 ) )
		return( CRYPT_ERROR_PERMISSION );

	/* If it's a check for a key generation capability (which is algorithm-
	   type independent), we check it before performing any algorithm-
	   specific checks */
	if( checkType == RESOURCE_MESSAGE_CHECK_KEYGEN )
		{
		if( cryptInfoPtr->type == CONTEXT_HASH )
			return( CRYPT_ERROR_NOTAVAIL );	/* No key for hash algorithms */
		if( !needsKey( cryptInfoPtr ) )
			{
			setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_KEY,
						  CRYPT_ERRTYPE_ATTR_PRESENT );
			return( CRYPT_ERROR_INITED );
			}
		return( ( capabilityInfoPtr->generateKeyFunction != NULL ) ? \
				CRYPT_OK : CRYPT_ARGERROR_OBJECT );
		}

	/* Perform general checks */
	if( needsKey( cryptInfoPtr ) )
		{
		setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_KEY,
					  CRYPT_ERRTYPE_ATTR_ABSENT );
		return( CRYPT_ERROR_NOTINITED );
		}

	/* Check for hash, MAC, and conventional encryption contexts */
	if( checkType == RESOURCE_MESSAGE_CHECK_HASH )
		return( ( cryptInfoPtr->type == CONTEXT_HASH ) ? \
				CRYPT_OK : CRYPT_ARGERROR_OBJECT );
	if( checkType == RESOURCE_MESSAGE_CHECK_MAC )
		return( ( cryptInfoPtr->type == CONTEXT_MAC ) ? \
				CRYPT_OK : CRYPT_ARGERROR_OBJECT );
	if( checkType == RESOURCE_MESSAGE_CHECK_CRYPT )
		return( ( cryptInfoPtr->type != CONTEXT_CONV ) ? \
				CRYPT_ARGERROR_OBJECT : CRYPT_OK );

	/* Make sure it's a PKC context */
	if( cryptInfoPtr->type != CONTEXT_PKC )
		return( CRYPT_ARGERROR_OBJECT );
	if( checkType == RESOURCE_MESSAGE_CHECK_PKC )
		return( CRYPT_OK );

	/* Check for key-agreement algorithms */
	if( isKeyxAlgo( cryptAlgo ) )
		/* DH can never be used for encryption or signatures (if it is then
		   we call it Elgamal) and KEA is explicitly for key agreement only */
		return( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_PRIVATE || \
				  checkType == RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT || \
				  checkType == RESOURCE_MESSAGE_CHECK_PKC_KA_IMPORT ) ? \
				CRYPT_OK : CRYPT_ARGERROR_OBJECT );
	if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT || \
		  checkType == RESOURCE_MESSAGE_CHECK_PKC_KA_IMPORT ) )
		return( CRYPT_ARGERROR_OBJECT );	/* Must be a key agreement algorithm */

	/* Check that the algorithm complies and the capability is available */
	if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT || \
		  checkType == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT ) && \
		cryptAlgo == CRYPT_ALGO_DSA )
		return( CRYPT_ARGERROR_OBJECT );	/* Must be an encryption algorithm */
	if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT && \
		  capabilityInfoPtr->encryptFunction == NULL ) || \
		( checkType == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT && \
		  capabilityInfoPtr->decryptFunction == NULL ) || \
		( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_SIGN || \
			checkType == RESOURCE_MESSAGE_CHECK_CA ) && \
		  capabilityInfoPtr->signFunction == NULL ) || \
		( checkType == RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK && \
		  capabilityInfoPtr->sigCheckFunction == NULL ) )
		return( CRYPT_ARGERROR_OBJECT );	/* Capability not supported */

	/* Check that it's a private key if this is required */
	if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_PRIVATE || \
		  checkType == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT || \
		  checkType == RESOURCE_MESSAGE_CHECK_PKC_SIGN || \
		  checkType == RESOURCE_MESSAGE_CHECK_CA ) && \
		cryptInfoPtr->ctxPKC.isPublicKey )
		return( CRYPT_ARGERROR_OBJECT );

	return( CRYPT_OK );
	}

/* Handle data sent to or read from a context */

static int exitNotInited( CRYPT_INFO *cryptInfoPtr,
						  const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	setErrorInfo( cryptInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT );
	return( CRYPT_ERROR_NOTINITED );
	}

static int processGetAttribute( CRYPT_INFO *cryptInfoPtr,
								void *messageDataPtr, const int messageValue )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
	const CONTEXT_TYPE contextType = cryptInfoPtr->type;
	int *valuePtr = ( int * ) messageDataPtr, value;

	switch( messageValue )
		{
		case CRYPT_ATTRIBUTE_ERRORTYPE:
			*valuePtr = cryptInfoPtr->errorType;
			return( CRYPT_OK );

		case CRYPT_ATTRIBUTE_ERRORLOCUS:
			*valuePtr = cryptInfoPtr->errorLocus;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_ALGO:
			*valuePtr = capabilityInfoPtr->cryptAlgo;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_MODE:
			assert( contextType == CONTEXT_CONV );
			*valuePtr = cryptInfoPtr->ctxConv.mode;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_KEYSIZE:
			assert( contextType == CONTEXT_CONV || \
					contextType == CONTEXT_PKC || \
					contextType == CONTEXT_MAC );
			if( contextType == CONTEXT_CONV )
				value = cryptInfoPtr->ctxConv.userKeyLength;
			else
				if( contextType == CONTEXT_MAC )
					value = cryptInfoPtr->ctxMAC.userKeyLength;
				else
					value = bitsToBytes( cryptInfoPtr->ctxPKC.keySizeBits );
			if( !value )
				/* If a key hasn't been loaded yet, we return the default 
				   key size */
				value = cryptInfoPtr->capabilityInfo->keySize;
			*valuePtr = value;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_BLOCKSIZE:
			if( contextType == CONTEXT_CONV && \
				( cryptInfoPtr->ctxConv.mode == CRYPT_MODE_CFB || \
				  cryptInfoPtr->ctxConv.mode == CRYPT_MODE_OFB ) )
				*valuePtr = 1;	/* Block cipher in stream mode */
			else
				*valuePtr = capabilityInfoPtr->blockSize;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_IVSIZE:
			assert( contextType == CONTEXT_CONV );
			if( !needsIV( cryptInfoPtr->ctxConv.mode ) || \
				isStreamCipher( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
				return( CRYPT_ERROR_NOTAVAIL );
			*valuePtr = capabilityInfoPtr->blockSize;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_KEYING_ALGO:
			assert( contextType == CONTEXT_CONV || \
					contextType == CONTEXT_MAC );
			if( contextType == CONTEXT_CONV )
				value = cryptInfoPtr->ctxConv.keySetupAlgorithm;
			else
				value = cryptInfoPtr->ctxMAC.keySetupAlgorithm;
			if( !value )
				return( exitNotInited( cryptInfoPtr,
						CRYPT_CTXINFO_KEYING_ALGO ) );
			*valuePtr = value;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_KEYING_ITERATIONS:
			assert( contextType == CONTEXT_CONV || \
					contextType == CONTEXT_MAC );
			if( contextType == CONTEXT_CONV )
				value = cryptInfoPtr->ctxConv.keySetupIterations;
			else
				value = cryptInfoPtr->ctxMAC.keySetupIterations;
			if( !value )
				return( exitNotInited( cryptInfoPtr,
						CRYPT_CTXINFO_KEYING_ITERATIONS ) );
			*valuePtr = value;
			return( CRYPT_OK );

		case CRYPT_IATTRIBUTE_DEVICEOBJECT:
			*valuePtr = ( int ) cryptInfoPtr->deviceObject;
			return( CRYPT_OK );
		}

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

static int processGetAttributeS( CRYPT_INFO *cryptInfoPtr,
								 void *messageDataPtr, const int messageValue )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
	const CONTEXT_TYPE contextType = cryptInfoPtr->type;
	RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
	STREAM stream;
	int status;

	switch( messageValue )
		{
		case CRYPT_CTXINFO_NAME_ALGO:
			return( attributeCopy( msgData, capabilityInfoPtr->algoName,
								   strlen( capabilityInfoPtr->algoName ) ) );

		case CRYPT_CTXINFO_NAME_MODE:
			assert( contextType == CONTEXT_CONV );
			switch( cryptInfoPtr->ctxConv.mode )
				{
				case CRYPT_MODE_ECB:
					return( attributeCopy( msgData, "ECB", 3 ) );
				case CRYPT_MODE_CBC:
					return( attributeCopy( msgData, "CBC", 3 ) );
				case CRYPT_MODE_CFB:
					return( attributeCopy( msgData, "CFB", 3 ) );
				case CRYPT_MODE_OFB:
					return( attributeCopy( msgData, "OFB", 3 ) );
				}
			assert( NOTREACHED );

		case CRYPT_CTXINFO_KEYING_SALT:
			assert( contextType == CONTEXT_CONV || \
					contextType == CONTEXT_MAC );
			if( contextType == CONTEXT_CONV )
				{
				if( !cryptInfoPtr->ctxConv.saltLength )
					return( exitNotInited( cryptInfoPtr,
							CRYPT_CTXINFO_KEYING_SALT ) );
				return( attributeCopy( msgData, cryptInfoPtr->ctxConv.salt,
									   cryptInfoPtr->ctxConv.saltLength ) );
				}
			if( !cryptInfoPtr->ctxMAC.saltLength )
				return( exitNotInited( cryptInfoPtr,
						CRYPT_CTXINFO_KEYING_SALT ) );
			return( attributeCopy( msgData, cryptInfoPtr->ctxMAC.salt,
								   cryptInfoPtr->ctxMAC.saltLength ) );

		case CRYPT_CTXINFO_IV:
			assert( contextType == CONTEXT_CONV );
			if( !needsIV( cryptInfoPtr->ctxConv.mode ) || \
				isStreamCipher( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
				return( CRYPT_ERROR_NOTAVAIL );
			if( !cryptInfoPtr->ctxConv.ivSet )
				return( exitNotInited( cryptInfoPtr, CRYPT_CTXINFO_IV ) );
			return( attributeCopy( msgData, cryptInfoPtr->ctxConv.iv,
								   cryptInfoPtr->ctxConv.ivLength ) );

		case CRYPT_CTXINFO_HASHVALUE:
			assert( contextType == CONTEXT_HASH || \
					contextType == CONTEXT_MAC );
			if( contextType == CONTEXT_HASH )
				{
				if( !cryptInfoPtr->ctxHash.done )
					return( CRYPT_ERROR_INCOMPLETE );
				return( attributeCopy( msgData, cryptInfoPtr->ctxHash.hash,
									   capabilityInfoPtr->blockSize ) );
				}
			if( !cryptInfoPtr->ctxMAC.done )
				return( CRYPT_ERROR_INCOMPLETE );
			return( attributeCopy( msgData, cryptInfoPtr->ctxMAC.mac,
								   capabilityInfoPtr->blockSize ) );

		case CRYPT_CTXINFO_LABEL:
			if( !cryptInfoPtr->labelSize )
				return( exitNotInited( cryptInfoPtr, CRYPT_CTXINFO_LABEL ) );
			return( attributeCopy( msgData, cryptInfoPtr->label,
								   cryptInfoPtr->labelSize ) );

		case CRYPT_IATTRIBUTE_KEYID:
			assert( contextType == CONTEXT_PKC );
			return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.keyID,
								   KEYID_SIZE ) );

		case CRYPT_IATTRIBUTE_PGP_KEYID:
			assert( contextType == CONTEXT_PKC );
			if( cryptInfoPtr->capabilityInfo->cryptAlgo != CRYPT_ALGO_RSA )
				return( CRYPT_ERROR_NOTFOUND );
			return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.pgpKeyID,
								   PGP_KEYID_SIZE ) );

		case CRYPT_IATTRIBUTE_OPENPGP_KEYID:
			assert( contextType == CONTEXT_PKC );
			assert( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA || \
					cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
					cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL );
			return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.openPGPKeyID,
								   PGP_KEYID_SIZE ) );

		case CRYPT_IATTRIBUTE_DOMAINPARAMS:
			assert( contextType == CONTEXT_PKC );
			return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.domainParamPtr,
								   cryptInfoPtr->ctxPKC.domainParamSize ) );

		case CRYPT_IATTRIBUTE_PUBLICVALUE:
			assert( contextType == CONTEXT_PKC );
			return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.publicValuePtr,
								   cryptInfoPtr->ctxPKC.publicValueSize ) );

		case CRYPT_IATTRIBUTE_PUBLICKEY:
			assert( contextType == CONTEXT_PKC );
			assert( cryptInfoPtr->ctxPKC.keySet );
			if( cryptInfoPtr->ctxPKC.publicKeyInfo != NULL )
				/* If the data is available in pre-encoded form, copy it 
				   out */
				return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.publicKeyInfo,
									   cryptInfoPtr->ctxPKC.publicKeyInfoSize ) );

			/* Write the public key info to the message buffer */
			sMemOpen( &stream, msgData->data, msgData->length );
			status = writePublicKey( &stream, cryptInfoPtr );
			if( cryptStatusOK( status ) )
				msgData->length = stell( &stream );
			sMemDisconnect( &stream );
			return( status );

		case CRYPT_IATTRIBUTE_SSH1_PUBLICKEY:
			assert( contextType == CONTEXT_PKC );

			/* Write the SSHv1-format key data from the context */
			sMemOpen( &stream, msgData->data, msgData->length );
			status = writeSsh1PublicKey( &stream, cryptInfoPtr );
			if( cryptStatusOK( status ) )
				msgData->length = stell( &stream );
			sMemDisconnect( &stream );

⌨️ 快捷键说明

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