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

📄 cryptusr.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		}
	return( status );
	}

/****************************************************************************
*																			*
*							User Management Functions						*
*																			*
****************************************************************************/

/* Perform a zeroise */

static int zeroiseUsers( void )
	{
	CRYPT_KEYSET iIndexKeyset;
	RESOURCE_DATA msgData;
	STREAM stream;
	static const BYTE zeroUserData[] = { 0x30, 0x00 };
	BYTE buffer[ KEYSET_BUFFERSIZE ];
	void *bufPtr = buffer;
	int length, status;

	/* Open the index file and read the index entries from it.  We open it in
	   exclusive mode and keep it open to ensure that noone else can access 
	   it while the zeroise is occurring */
	status = openUserKeyset( &iIndexKeyset, "index", 
							 CRYPT_IKEYOPT_EXCLUSIVEACCESS );
	if( cryptStatusError( status ) )
		/* If there's no index file present, we're already in the zeroised 
		   state */
		return( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );
	status = readUserData( iIndexKeyset, CRYPT_IATTRIBUTE_USERINDEX,
						   &bufPtr, &length, 0 );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
		if( bufPtr != buffer )
			free( bufPtr );
		return( status );
		}

	/* Step through each entry clearing the user info for it */
	sMemConnect( &stream, bufPtr, length );
	while( stell( &stream ) < length )
		{
		STREAM fileStream;
		char userFilePath[ MAX_PATH_LENGTH + 128 ];	/* Protection for Windows */
		char userFileName[ 16 ];
		long fileRef;

		/* Get the file reference for this user */
		readSequence( &stream, NULL );
		readUniversal( &stream );
		readUniversal( &stream );
		readUniversal( &stream );
		status = readShortInteger( &stream, &fileRef );
		if( cryptStatusError( status ) )
			continue;

		/* Erase the given user keyset */
		sprintf( userFileName, "u%06x", fileRef );
		fileBuildCryptlibPath( userFilePath, userFileName, FALSE );
		status = sFileOpen( &fileStream, userFilePath, 
							FILE_READ | FILE_WRITE | FILE_EXCLUSIVE_ACCESS );
		if( cryptStatusError( status ) )
			continue;
		fileClearToEOF( &fileStream );
		sFileClose( &fileStream );
		fileUnlink( userFilePath );
		}
	sMemDisconnect( &stream );
	if( bufPtr != buffer )
		free( bufPtr );

	/* Erase the index file by setting zero-length user index info, which
	   results in an empty keyset which is erased on close */
	setResourceData( &msgData, ( void * ) zeroUserData, 2 );
	status = krnlSendMessage( iIndexKeyset, RESOURCE_IMESSAGE_SETATTRIBUTE_S, 
							  &msgData, CRYPT_IATTRIBUTE_USERINDEX );
	krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
	
	return( status );
	}

/* Create a user object keyset */

static int createUserKeyset( CRYPT_KEYSET *iCreatedKeyset, 
							 USER_INFO *userInfoPtr )
	{
	CRYPT_KEYSET iIndexKeyset, iUserKeyset;
	BOOLEAN newIndex = FALSE;
	BYTE buffer[ KEYSET_BUFFERSIZE ];
	void *bufPtr = buffer;
	char userFileName[ 16 ];
	int fileRef, length, status;

	/* Clear return value */
	*iCreatedKeyset = CRYPT_ERROR;

	/* Try and open the config file.  If we can't open it and the return 
	   status is something other than an indication that the file is in use,
	   it means the file doesn't exist so we try and create it instead.
	   Performing the create is safe because the stream subsystem will
	   either return an appropriate error code to indicate that the file is 
	   locked by another thread/process or will block until it becomes 
	   unlocked, depending on how the OS implements file locking */
	status = openUserKeyset( &iIndexKeyset, "index", 
							 CRYPT_IKEYOPT_EXCLUSIVEACCESS );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_BUSY )
		{
		status = openUserKeyset( &iIndexKeyset, "index", 
								 CRYPT_KEYOPT_CREATE );
		newIndex = TRUE;
		}
	if( cryptStatusError( status ) )
		return( status );	

	/* If there's index data present, read it and make sure the new user 
	   isn't already present */
	if( !newIndex )
		{
		/* Read the index entries from the keyset */
		status = readUserData( iIndexKeyset, CRYPT_IATTRIBUTE_USERINDEX,
							   &bufPtr, &length, MAX_USERINDEX_SIZE );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
			if( bufPtr != buffer )
				free( bufPtr );
			return( status );
			}

		/* Check whether this user is present in the index */
		status = findUser( bufPtr, length, USERID_NAME, userInfoPtr->userName, 
						   userInfoPtr->userNameLength );
		if( !cryptStatusError( status ) )
			{
			krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
			if( bufPtr != buffer )
				free( bufPtr );
			return( CRYPT_ERROR_DUPLICATE );
			}

		/* Make sure the userID is unique */
		do
			{
			status = findUser( bufPtr, length, USERID_USERID, 
							   userInfoPtr->userID, KEYID_SIZE );
			if( !cryptStatusError( status ) )
				getNonce( userInfoPtr->userID, KEYID_SIZE );
			}
		while( !cryptStatusError( status ) );
		}
	else
		/* No users present yet, use the first user entry */
		fileRef = length = 0;

	/* Create the user keyset */
	sprintf( userFileName, "u%06x", fileRef );
	status = openUserKeyset( &iUserKeyset, userFileName, 
							 CRYPT_KEYOPT_CREATE );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
		if( bufPtr != buffer )
			free( bufPtr );
		return( status );
		}

	/* Update the index file */
	status = insertIndexEntry( userInfoPtr, bufPtr, &length );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, bufPtr, length );
		status = krnlSendMessage( iIndexKeyset, 
								  RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData, 
								  CRYPT_IATTRIBUTE_USERINDEX );
		}
	if( cryptStatusError( status ) )
		/* We couldn't update the index file, delete the newly-created user
		   keyset (since we haven't written anything to it, it's zero-length
		   so it's deleted automatically on close) */
		krnlSendNotifier( iUserKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
	else
		{
		userInfoPtr->fileRef = fileRef;
		*iCreatedKeyset = iUserKeyset;
		}
	krnlSendNotifier( iIndexKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );

	/* Clean up */
	if( bufPtr != buffer )
		free( bufPtr );
	return( status );
	}

/* Set/change the password for a user object */

static int setPassword( USER_INFO *userInfoPtr, const char *password, 
						const int passwordLength )
	{
	CRYPT_KEYSET iUserKeyset;
	int status;

	/* No-one can ever directly set the default SO password */
	if( passwordLength == PRIMARYSO_PASSWORD_LENGTH && \
		( !memcmp( password, PRIMARYSO_PASSWORD, 
				   PRIMARYSO_PASSWORD_LENGTH ) || \
		  !memcmp( password, PRIMARYSO_ALTPASSWORD, 
				   PRIMARYSO_PASSWORD_LENGTH ) ) )
		return( CRYPT_ERROR_WRONGKEY );

	/* If we're setting the password for the primary SO in the zeroised
	   state, create a new user keyset and SO authentication key and write
	   the details to the keyset */
	if( userInfoPtr->fileRef == -1 )
		{
		status = createUserKeyset( &iUserKeyset, userInfoPtr );
		assert( ( cryptStatusError( status ) && userInfoPtr->fileRef == -1 ) || \
				( cryptStatusOK( status ) && userInfoPtr->fileRef == 0 ) );
		if( cryptStatusOK( status ) )
			{
			/* Since this user is created implicitly, there's no userID set 
			   by an explicit create so we set it now.  Since this is 
			   effectively a self-created user we also set the creatorID to 
			   the userID */
			getNonce( userInfoPtr->userID, KEYID_SIZE );
			memcpy( userInfoPtr->creatorID, userInfoPtr->userID, 
					KEYID_SIZE );
			status = createSOKey( iUserKeyset, userInfoPtr, 
								  password, passwordLength );
			}
		if( cryptStatusOK( status ) )
			status = writeUserInfo( iUserKeyset, userInfoPtr, 
									userInfoPtr->iCryptContext );

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*status = createCAKey( iUserKeyset, userInfoPtr, password, passwordLength );*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
		}
	else
		{
		char userFileName[ 16 ];

		/* Open an existing user keyset */
		sprintf( userFileName, "u%06x", userInfoPtr->fileRef );
		status = openUserKeyset( &iUserKeyset, userFileName, 
								 CRYPT_KEYOPT_NONE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
	/* set state = USER_INITED */
	/* write MAC( ??? ) to user file - needs PKCS #15 changes */
	/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

	/* Close the keyset and commit the changes */
	krnlSendNotifier( iUserKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );

	/* The password has been set, we're now in the user inited state */
	userInfoPtr->state = USER_STATE_USERINITED;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							General User Object Functions					*
*																			*
****************************************************************************/

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

static int userMessageFunction( const CRYPT_USER cryptUser,
								const RESOURCE_MESSAGE_TYPE message,
								void *messageDataPtr, const int messageValue )
	{
	USER_INFO *userInfoPtr;

	getCheckInternalResource( cryptUser, userInfoPtr, OBJECT_TYPE_USER );

	/* Process destroy object messages */
	if( message == RESOURCE_MESSAGE_DESTROY )
		{
		/* Clean up any user-related crypto objects if necessary */
		if( userInfoPtr->iCryptContext != CRYPT_ERROR )
			krnlSendNotifier( userInfoPtr->iCryptContext,
							  RESOURCE_IMESSAGE_DECREFCOUNT );
		if( userInfoPtr->iKeyset != CRYPT_ERROR )
			krnlSendNotifier( userInfoPtr->iKeyset,
							  RESOURCE_IMESSAGE_DECREFCOUNT );

		/* Clean up the config options */
		endOptions( userInfoPtr->configOptions );

		/* Delete the objects locking variables and the object itself */
		unlockResource( userInfoPtr );
		deleteResourceLock( userInfoPtr );
		zeroise( userInfoPtr, sizeof( USER_INFO ) );
		free( userInfoPtr );

		return( CRYPT_OK );
		}

	/* Process attribute get/set/delete messages */
	if( isAttributeMessage( message ) )
		{
		char userFileName[ 16 ];
		void *data;
		int length, status;

		if( messageValue == CRYPT_USERINFO_PASSWORD )
			{
			RESOURCE_DATA *msgData = messageDataPtr;

			status = setPassword( userInfoPtr, msgData->data, 
								  msgData->length );
			unlockResourceExit( userInfoPtr, status );
			}
		if( messageValue == CRYPT_USERINFO_CAKEY_CERTSIGN || \
			messageValue == CRYPT_USERINFO_CAKEY_CRLSIGN || \
			messageValue == CRYPT_USERINFO_CAKEY_OCSPSIGN )
			{
			const int objectHandle = *( int * ) messageDataPtr;
			const int requiredKeyUsage = \
				( messageValue == CRYPT_USERINFO_CAKEY_CERTSIGN ) ? \
					CRYPT_KEYUSAGE_KEYCERTSIGN : \
				( messageValue == CRYPT_USERINFO_CAKEY_CRLSIGN ) ? \
					CRYPT_KEYUSAGE_CRLSIGN : \
					( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
					  CRYPT_KEYUSAGE_NONREPUDIATION );
			int value;

			/* Make sure we've been given a signing key */
			status = krnlSendMessage( objectHandle, RESOURCE_IMESSAGE_CHECK, 
									  NULL, RESOURCE_MESSAGE_CHECK_PKC_SIGN );
			if( cryptStatusError( status ) )
				return( CRYPT_ARGERROR_NUM1 );

			/* Make sure the object has an initialised cert of the correct 
			   type associated with it */
			status = krnlSendMessage( objectHandle, 
									  RESOURCE_IMESSAGE_GETATTRIBUTE, 
									  &value, CRYPT_CERTINFO_IMMUTABLE );
			if( cryptStatusError( status ) || !value )
				return( CRYPT_ARGERROR_NUM1 );
			status = krnlSendMessage( objectHandle, 
									  RESOURCE_IMESSAGE_GETATTRIBUTE,
									  &value, CRYPT_CERTINFO_CERTTYPE );
			if( cryptStatusError( status ) ||
				( value != CRYPT_CERTTYPE_CERTIFICATE && \
				  value != CRYPT_CERTTYPE_CERTCHAIN ) )
				return( CRYPT_ARGERROR_NUM1 );

			/* Make sure the key usage required for this action is 
			   permitted.  OCSP is a bit difficult since the key may or may
			   not have an OCSP extended usage (depending on whether the CA 
			   bothers to set it or not, even if they do they may delegate 
			   the functionality to a short-term generic signing key) and the
			   signing ability may be indicated by either a digital signature
			   flag or a nonrepudiation flag depending on whether the CA
			   considers an OCSP signature to be short or long-term, so we
			   just check for a generic signing ability */
			status = krnlSendMessage( objectHandle, 

⌨️ 快捷键说明

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