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

📄 cryptkey.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	keysetInfoPtr->subType = subType;
	memcpy( keysetInfoPtr->keysetFile->fileName, name, nameLength );
	keysetInfoPtr->keysetFile->fileName[ nameLength ] = '\0';
	memcpy( &keysetInfoPtr->keysetFile->stream, stream, sizeof( STREAM ) );

	/* Make sure that we don't accidentally reuse the standalone stream */
	memset( stream, 0, sizeof( STREAM ) );

	/* Set up the access information for the file */
	switch( keysetInfoPtr->subType )
		{
		case KEYSET_SUBTYPE_PKCS12:
			status = setAccessMethodPKCS12( keysetInfoPtr );
			break;

		case KEYSET_SUBTYPE_PKCS15:
			status = setAccessMethodPKCS15( keysetInfoPtr );
			break;

		case KEYSET_SUBTYPE_PGP_PUBLIC:
			status = setAccessMethodPGPPublic( keysetInfoPtr );
			break;

		case KEYSET_SUBTYPE_PGP_PRIVATE:
			status = setAccessMethodPGPPrivate( keysetInfoPtr );
			break;

		default:
			retIntError();
		}
	if( cryptStatusError( status ) )
		return( status );
	ENSURES( keysetInfoPtr->initFunction != NULL && \
			 keysetInfoPtr->shutdownFunction != NULL && \
			 keysetInfoPtr->getItemFunction != NULL );
	ENSURES( subType != SUBTYPE_KEYSET_FILE || \
			 ( keysetInfoPtr->getSpecialItemFunction != NULL && \
			   keysetInfoPtr->setItemFunction != NULL && \
			   keysetInfoPtr->setSpecialItemFunction != NULL && \
			   keysetInfoPtr->deleteItemFunction != NULL && \
			   keysetInfoPtr->getFirstItemFunction != NULL && \
			   keysetInfoPtr->getNextItemFunction != NULL ) );

	/* Read the keyset contents into memory */
	sioctl( &keysetInfoPtr->keysetFile->stream, STREAM_IOCTL_IOBUFFER, 
			buffer, STREAM_BUFSIZE );
	status = keysetInfoPtr->initFunction( keysetInfoPtr, NULL, 0,
										  keysetInfoPtr->options );
	sioctl( &keysetInfoPtr->keysetFile->stream, STREAM_IOCTL_IOBUFFER, 
			NULL, 0 );
	if( cryptStatusError( status ) )
		return( status );

	/* If we've got the keyset open in read-only mode then we don't need to 
	   touch it again since everything is cached in-memory, so we can close 
	   the file stream */
	if( ( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 || \
		  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 || \
		  keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) && \
		( keysetInfoPtr->options == CRYPT_KEYOPT_READONLY ) )
		sFileClose( &keysetInfoPtr->keysetFile->stream );
	else
		{
		/* Remember that the stream is still open for further access */
		keysetInfoPtr->flags |= KEYSET_STREAM_OPEN;
		}
	keysetInfoPtr->flags |= KEYSET_OPEN;
	if( keysetInfoPtr->options == CRYPT_KEYOPT_CREATE )
		keysetInfoPtr->flags |= KEYSET_EMPTY;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Keyset Message Handler						*
*																			*
****************************************************************************/

/* Handle a message sent to a keyset object */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int keysetMessageFunction( INOUT TYPECAST( KEYSET_INFO * ) \
									void *objectInfoPtr,
								  IN_MESSAGE const MESSAGE_TYPE message,
								  void *messageDataPtr,
								  IN_INT_Z const int messageValue )
	{
	KEYSET_INFO *keysetInfoPtr = ( KEYSET_INFO * ) objectInfoPtr;
	int status;

	assert( isWritePtr( objectInfoPtr, sizeof( KEYSET_INFO ) ) );

	REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
	REQUIRES( messageValue >= 0 && messageValue < MAX_INTLENGTH_SHORT );

	/* Process the destroy object message */
	if( message == MESSAGE_DESTROY )
		{
		/* If the keyset is active, perform any required cleanup functions */
		if( keysetInfoPtr->flags & KEYSET_OPEN )
			{
			/* Shut down the keyset */
			status = keysetInfoPtr->shutdownFunction( keysetInfoPtr );
			if( cryptStatusError( status ) )
				{
				assert( INTERNAL_ERROR );

				/* The shutdown failed for some reason.  This can only 
				   really ever happen for file keysets, in general there's 
				   not much that we can do about this (see the long comment
				   about file-close failure conditions in io/file.c), 
				   however in order to avoid leaving a potentially corrupted
				   file on disk we try and delete it if the shutdown fails.
				   (There are a pile of tradeoffs to be made here, for 
				   example in theory we could rename the file to something
				   like .bak so that the user could try and recover 
				   whatever's left in there, however it's unlikely that 
				   they'll be able to do much with an unknown-condition 
				   binary blob and in any case since we have no idea what
				   condition the file is in it's probably best to remove it
				   rather than to leave who knows what lying around on 
				   disk) */
				if( keysetInfoPtr->type == KEYSET_FILE && \
					( keysetInfoPtr->flags & KEYSET_STREAM_OPEN ) )
					{
					sFileClose( &keysetInfoPtr->keysetFile->stream );
					fileErase( keysetInfoPtr->keysetFile->fileName );
					}
				}

			/* If it's a non-file keyset or a file keyset without an open
			   stream, we're done.  Since we cache all information in a file 
			   keyset and close the stream immediately afterwards if we've 
			   opened it in read-only mode, we only close the underlying 
			   stream for a file keyset if it's still active.  Note the 
			   distinction between the keyset being active and the stream 
			   being active, for file keysets the keyset can be active 
			   without being associated with an open stream */
			if( keysetInfoPtr->type != KEYSET_FILE || \
				!( keysetInfoPtr->flags & KEYSET_STREAM_OPEN ) )
				return( CRYPT_OK );

			/* The keyset has an open file stream */
			REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
					  ( keysetInfoPtr->flags & KEYSET_STREAM_OPEN ) );

			/* If the file keyset was updated in any way the update may have 
			   changed the overall file size, in which case we need to clear 
			   any leftover data from the previous version of the keyset 
			   before we close the file */
			if( keysetInfoPtr->flags & KEYSET_DIRTY )
				fileClearToEOF( &keysetInfoPtr->keysetFile->stream );

			/* Close the keyset file (the keyset-specific handler sees only 
			   an I/O stream and doesn't perform any file-level functions, 
			   so we have to do this here) */
			status = sFileClose( &keysetInfoPtr->keysetFile->stream );
			if( cryptStatusError( status ) )
				{
				/* Try and remove the keyset if the file close failed and 
				   would have left the file in an indeterminate state, see 
				   the comment in io/file.c for more information */
				fileErase( keysetInfoPtr->keysetFile->fileName );
				}
			else
				{
				/* If it's a newly-created empty keyset file or one in which 
				   all of the keys have been deleted, remove it.  This 
				   situation can occur if there's some sort of error on 
				   writing and no keys are ever written to the keyset */
				if( keysetInfoPtr->flags & KEYSET_EMPTY )
					fileErase( keysetInfoPtr->keysetFile->fileName );
				}
			}

		return( CRYPT_OK );
		}

	/* Process attribute get/set/delete messages */
	if( isAttributeMessage( message ) )
		{
		REQUIRES( message == MESSAGE_GETATTRIBUTE || \
				  message == MESSAGE_GETATTRIBUTE_S || \
				  message == MESSAGE_SETATTRIBUTE || \
				  message == MESSAGE_SETATTRIBUTE_S );

		/* If it's a keyset-specific attribute, forward it directly to
		   the low-level code */
#ifdef USE_LDAP
		if( messageValue >= CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS && \
			messageValue <= CRYPT_OPTION_KEYS_LDAP_EMAILNAME )
			{
			REQUIRES( keysetInfoPtr->type == KEYSET_LDAP );

			if( message == MESSAGE_SETATTRIBUTE || \
				message == MESSAGE_SETATTRIBUTE_S )
				{
				status = keysetInfoPtr->setAttributeFunction( keysetInfoPtr,
											messageDataPtr, messageValue );
				if( status == CRYPT_ERROR_INITED )
					{
					setErrorInfo( keysetInfoPtr, messageValue, 
								  CRYPT_ERRTYPE_ATTR_PRESENT );
					return( CRYPT_ERROR_INITED );
					}
				}
			else
				{
				REQUIRES( message == MESSAGE_GETATTRIBUTE || \
						  message == MESSAGE_GETATTRIBUTE_S );

				status = keysetInfoPtr->getAttributeFunction( keysetInfoPtr,
											messageDataPtr, messageValue );
				if( status == CRYPT_ERROR_NOTFOUND )
					{
					setErrorInfo( keysetInfoPtr, messageValue, 
								  CRYPT_ERRTYPE_ATTR_ABSENT );
					return( CRYPT_ERROR_NOTFOUND );
					}
				}
			return( status );
			}
#endif /* USE_LDAP */

		if( message == MESSAGE_GETATTRIBUTE )
			return( getKeysetAttribute( keysetInfoPtr, 
										( int * ) messageDataPtr,
										messageValue ) );
		if( message == MESSAGE_GETATTRIBUTE_S )
			return( getKeysetAttributeS( keysetInfoPtr, 
										 ( MESSAGE_DATA * ) messageDataPtr,
										 messageValue ) );
		if( message == MESSAGE_SETATTRIBUTE )
			{
			/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message 
			   with no parameters so we don't pass it down to the attribute-
			   handling code */
			if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
				return( CRYPT_OK );

			return( setKeysetAttribute( keysetInfoPtr, 
										*( ( int * ) messageDataPtr ),
										messageValue ) );
			}
		if( message == MESSAGE_SETATTRIBUTE_S )
			{
			const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;

			return( setKeysetAttributeS( keysetInfoPtr, msgData->data, 
										 msgData->length, messageValue ) );
			}

		retIntError();
		}

	/* Process messages that check a keyset */
	if( message == MESSAGE_CHECK )
		{
		/* The check for whether this keyset type can contain an object that 
		   can perform the requested operation has already been performed by 
		   the kernel so there's nothing further to do here */
		REQUIRES( ( messageValue != MESSAGE_CHECK_PKC_PRIVATE && \
					messageValue != MESSAGE_CHECK_PKC_DECRYPT && \
					messageValue != MESSAGE_CHECK_PKC_DECRYPT_AVAIL && \
					messageValue != MESSAGE_CHECK_PKC_SIGN && \
					messageValue != MESSAGE_CHECK_PKC_SIGN_AVAIL ) || 
				  ( keysetInfoPtr->type != KEYSET_DBMS && \
					keysetInfoPtr->type != KEYSET_LDAP && \
					keysetInfoPtr->type != KEYSET_HTTP ) );

		return( CRYPT_OK );
		}

	/* Process object-specific messages */
	if( message == MESSAGE_KEY_GETKEY )
		{
		MESSAGE_KEYMGMT_INFO *getkeyInfo = \
								( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
		CONST_INIT_STRUCT_3( KEYID_INFO keyIDinfo, \
							 getkeyInfo->keyIDtype, getkeyInfo->keyID, \
							 getkeyInfo->keyIDlength );
		BYTE keyIDbuffer[ KEYID_SIZE + 8 ];

		CONST_SET_STRUCT( keyIDinfo.keyIDtype = getkeyInfo->keyIDtype; \
						  keyIDinfo.keyID = getkeyInfo->keyID; \
						  keyIDinfo.keyIDlength = getkeyInfo->keyIDlength );

		REQUIRES( keyIDinfo.keyIDtype != CRYPT_KEYID_NONE && \
				  keyIDinfo.keyID != NULL && \
				  keyIDinfo.keyIDlength >= MIN_NAME_LENGTH && \
				  keyIDinfo.keyIDlength < MAX_ATTRIBUTE_SIZE );
		REQUIRES( messageValue != KEYMGMT_ITEM_PRIVATEKEY || \
				  keysetInfoPtr->type == KEYSET_FILE );
		REQUIRES( ( messageValue != KEYMGMT_ITEM_SECRETKEY && \
					messageValue != KEYMGMT_ITEM_DATA ) || \
				  ( keysetInfoPtr->type == KEYSET_FILE && \
					keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) );
		REQUIRES( ( messageValue != KEYMGMT_ITEM_REQUEST && \
					messageValue != KEYMGMT_ITEM_REVOCATIONINFO && \
					messageValue != KEYMGMT_ITEM_PKIUSER ) || \
				  keysetInfoPtr->type == KEYSET_DBMS );

		/* Get the key */
		resetErrorInfo( keysetInfoPtr );
		status = initKeysetUpdate( keysetInfoPtr, &keyIDinfo, keyIDbuffer,
								   KEYID_SIZE, TRUE );
		if( cryptStatusError( status ) )
			return( status );
		return( keysetInfoPtr->getItemFunction( keysetInfoPtr,
							&getkeyInfo->cryptHandle, messageValue,
							keyIDinfo.keyIDtype, keyIDinfo.keyID, 
							keyIDinfo.keyIDlength, getkeyInfo->auxInfo, 
							&getkeyInfo->auxInfoLength, 
							getkeyInfo->flags ) );
		}
	if( message == MESSAGE_KEY_SETKEY )
		{
		MESSAGE_KEYMGMT_INFO *setkeyInfo = \
								( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;

		REQUIRES( messageValue != KEYMGMT_ITEM_PRIVATEKEY || \
				  ( keysetInfoPtr->type == KEYSET_FILE && \
					( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 || \
					  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 ) ) );
		REQUIRES( ( messageValue != KEYMGMT_ITEM_SECRETKEY && \
					messageValue != KEYMGMT_ITEM_DATA ) || \
				  ( keysetInfoPtr->type == KEYSET_FILE && \
					keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) );
		REQUIRES( ( messageValue != KEYMGMT_ITEM_REQUEST && \
					messageValue != KEYMGMT_ITEM_REVOCATIONINFO && \
					messageValue != KEYMGMT_ITEM_PKIUSER ) || \
				  ( keysetInfoPtr->type == KEYSET_DBMS ) );

		/* Set the key.  This is currently the only way to associate a 
		   certificate with a context (that is, it's not possible to add a 
		   certificate to an existing context directly).  At first glance 
		   this should be possible since the required access checks are 
		   performed by the kernel: The object is of the correct type (a 
		   certificate), in the high state (it's been signed), and the 
		   certificate owner and context owner are the same.  However the 
		   actual process of attaching the certificate to the context is 
		   quite tricky.  The certificate will have a public-key context 
		   already attached to it from when the certificate was created or 
		   imported.  In order to attach this to the other context we'd need 
		   to first destroy the context associated with the certificate and 
		   then replace it with the other context, which is both messy and 
		   non-atomic.  There are also complications surrounding use with 
		   devices, where contexts aren't really full cryptlib objects but 
		   just dummy values that point back to the device for handling of 
		   operations.  Going via a keyset/device bypasses these issues, but 
		   doing it directly shows up all of these problems */
		resetErrorInfo( keysetInfoPtr );
		status = initKeysetUpdate( keysetInfoPtr, NULL, NULL, 0, FALSE );
		if( cryptStatusError( status ) )
			return( status );
		status = keysetInfoPtr->setItemFunction( keysetInfoPtr,
							setkeyInfo->cryptHandle, messageValue,
							setkeyInfo->auxInfo, setkeyInfo->auxInfoLength,
							setkeyInfo->flags );
		if( cryptStatusError( status ) )
			return( status );

		/* The update succeeded, remember that the data in the keyset has 
		   changed */
		keysetInfoPtr->flags |= KEYSET_DIRTY;
		keysetInfoPtr->flags &= ~KEYSET_EMPTY;

		return( CRYPT_OK );
		}
	if( message == MESSAGE_KEY_DELETEKEY )
		{
		MESSAGE_KEYMGMT_INFO *deletekeyInfo = \
								( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
		CONST_INIT_STRUCT_3( KEYID_INFO keyIDinfo, \
							 deletekeyInfo->keyIDtype, deletekeyInfo->keyID, \
							 deletekeyInfo->keyIDlength );
		BYTE keyIDbuffer[ KEYID_SIZE + 8 ];

		CONST_SET_STRUCT( keyIDinfo.keyIDtype = deletekeyInfo->keyIDtype; \
						  keyIDinfo.keyID = deletekeyInfo->keyID; \
						  keyIDinfo.keyIDlength = deletekeyInfo->keyIDlength );

		REQUIRES( keyIDinfo.keyIDtype != CRYPT_KEYID_NONE && \
				  keyIDinfo.keyID != NULL && \
				  keyIDinfo.keyIDlength >= MIN_NAME_LENGTH && \
				  keyIDinfo.keyIDlength < MAX_ATTRIBUTE_SIZE );

		/* Delete the key */
		resetErrorInfo( keysetInfoPtr );
		status = initKeysetUpdate( keysetInfoPtr, &keyIDinfo, keyIDbuffer,
								   KEYID_SIZE, FALSE );
		if( cryptStatusError( status ) )
			return( status );
		status = keysetInfoPtr->deleteItemFunction( keysetInfoPtr,
							messageValue, keyIDinfo.keyIDtype, 
							keyIDinfo.keyID, keyIDinfo.keyIDlength );
		if( cryptStatusOK( status ) )
			{
			/* The update succeeded, remember that the data in the keyset 
			   has changed */
			keysetInfoPtr->flags |= KEYSET_DIRTY;
			}
		return( status );
		}
	if( message == MESSAGE_KEY_GETFIRSTCERT )
		{
		MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
								( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
		CONST_INIT_STRUCT_3( KEYID_INFO keyIDinfo, \
							 getnextcertInfo->keyIDtype, getnextcertInfo->keyID, \
							 getnextcertInfo->keyIDlength );
		BYTE keyIDbuffer[ KEYID_SIZE + 8 ];

		CONST_SET_STRUCT( keyIDinfo.keyIDtype = getnextcertInfo->keyIDtype; \
						  keyIDinfo.keyID = getnextcertInfo->keyID; \
						  keyIDinfo.keyIDlength = getnextcertInfo->keyIDlength );

⌨️ 快捷键说明

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