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

📄 cryptusr.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*							cryptlib User Routines							*
*						Copyright Peter Gutmann 1999-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "crypt.h"
#ifdef INC_ALL
  #include "asn1.h"
  #include "asn1_ext.h"
#else
  #include "misc/asn1.h"
  #include "misc/asn1_ext.h"
#endif /* Compiler-specific includes */

/* States for the user object */

typedef enum {
	USER_STATE_NONE,				/* No initialisation state */
	USER_STATE_SOINITED,			/* SSO inited, not usable */
	USER_STATE_USERINITED,			/* User inited, usable */
	USER_STATE_LOCKED,				/* Disabled, not usable */
	USER_STATE_LAST					/* Last possible state */
	} USER_STATE_TYPE;

/* The structure which stores the information on a user */

typedef struct UI {
	/* Control and status information */
	CRYPT_USER_TYPE type;			/* User type */
	USER_STATE_TYPE state;			/* User object state */
	BYTE userName[ CRYPT_MAX_TEXTSIZE + 1 ];
	int userNameLength;				/* User name */
	BYTE userID[ KEYID_SIZE ], creatorID[ KEYID_SIZE ];
									/* ID of user and creator of this user */
	int fileRef;					/* User info keyset reference */

	/* Configuration options for this user.  These aren't handled directly by
	   the user object code but are managed externally through the config 
	   code, so they're just treated as a dynamically-allocated blob within
	   the user object */
	void *configOptions;

	/* Certificate trust information for this user, and a flag indicating 
	   whether the trust info has changed and potentially needs to be 
	   committed to disk */
	void *trustInfoPtr;
	BOOLEAN trustInfoChanged;

	/* The user object contains an associated keyset which is used to store
	   user information to disk, in addition for SOs and CAs it also contains
	   an associated encryption context, either a private key (for an SO) or
	   a conventional key (for a CA) */
	CRYPT_KEYSET iKeyset;			/* Keyset */
	CRYPT_CONTEXT iCryptContext;	/* Private/secret key */

	/* Error information */
	CRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */
	CRYPT_ERRTYPE_TYPE errorType;	/* Error type */

	/* The object's handle, used when sending messages to the object when
	   only the xxx_INFO is available */
	CRYPT_HANDLE objectHandle;
	} USER_INFO;

/* User information as read from the user info file */

typedef struct {
	CRYPT_USER_TYPE type;			/* User type */
	USER_STATE_TYPE state;			/* User state */
	BYTE userName[ CRYPT_MAX_TEXTSIZE + 1 ];
	int userNameLength;				/* User name */
	BYTE userID[ KEYID_SIZE ];		/* User ID */
	BYTE creatorID[ KEYID_SIZE ];	/* Creator ID */
	int fileRef;					/* User info file reference */
	} USER_FILE_INFO;

/* Default and primary SO user info.  The default user is a special type 
   which has both normal user and SO privileges.  This is because in its 
   usual usage mode where cryptlib is functioning as a single-user system 
   the user doesn't know about the existence of user objects and just wants 
   everything to work the way they expect.  Because of this, the default user 
   has to be able to perform the full range of available operations, 
   requiring that they appear as both a normal user and an SO.
   
   For now the default user is marked as an SO user because the kernel checks
   don't allow dual-type objects and some operations require that the user be
   at least an SO user, once a distinction is made between SOs and users this
   will need to be fixed */

static const FAR_BSS USER_FILE_INFO defaultUserInfo = {
#if 0	/* Disabled since ACL checks are messed up by dual-user, 18/5/02 */
	CRYPT_USER_NONE,				/* Special-case SO+normal user */
#else
	CRYPT_USER_SO,					/* Special-case SO user */
#endif /* 0 */
	USER_STATE_USERINITED,			/* Initialised, ready for use */
	"Default cryptlib user", 21,	/* Pre-set user name */
	"<<<<DEFAULT_USER>>>>", "<<<<DEFAULT_USER>>>>", 
	CRYPT_UNUSED					/* No corresponding user file */
	};
static const FAR_BSS USER_FILE_INFO primarySOInfo = {
	CRYPT_USER_SO,					/* SO user */
	USER_STATE_SOINITED,			/* SO initialised, not ready for use */
	"Security officer", 16,			/* Pre-set user name */
	"<<<PRIMARYSO_USER>>>", "<<<TETRAGRAMMATON>>>",
	-1			/* No user file when starting from zeroised state */
	};

/* The primary SO password after zeroisation */

#define PRIMARYSO_PASSWORD		"zeroised"
#define PRIMARYSO_ALTPASSWORD	"zeroized"
#define PRIMARYSO_PASSWORD_LENGTH 8

/* Prototypes for functions in cryptcfg.c */

int initOptions( void **configOptionsPtr );
void endOptions( void *configOptions );
int setOption( void *configOptions, const CRYPT_ATTRIBUTE_TYPE option, 
			   const int value );
int setOptionString( void *configOptions, const CRYPT_ATTRIBUTE_TYPE option, 
					 const char *value, const int valueLength );
int getOption( void *configOptions, const CRYPT_ATTRIBUTE_TYPE option );
char *getOptionString( void *configOptions, 
					   const CRYPT_ATTRIBUTE_TYPE option );
int readConfig( const CRYPT_USER iCryptUser, const char *fileName,
				void *trustInfoPtr );
int encodeConfigData( void *configOptions, const char *fileName, 
					  void *trustInfoPtr, void **data, int *length );
int commitConfigData( const CRYPT_USER cryptUser, const char *fileName, 
					  const void *data, const int length );

/* Prototypes for cert trust management functions */

int initTrustInfo( void **trustInfoPtrPtr );
void endTrustInfo( void *trustInfoPtr );
int addTrustEntry( void *trustInfoPtr, const CRYPT_CERTIFICATE iCryptCert, 
				   const void *certObject, const int certObjectLength, 
				   const BOOLEAN addSingleCert );
void deleteTrustEntry( void *trustInfoPtr, void *entryToDelete );
void *findTrustEntry( void *trustInfoPtr, const CRYPT_CERTIFICATE cryptCert,
					  const BOOLEAN getIssuerEntry );
CRYPT_CERTIFICATE getTrustedCert( void *trustInfoPtr );
int enumTrustedCerts( void *trustInfoPtr, const CRYPT_CERTIFICATE iCryptCtl, 
					  const CRYPT_KEYSET iCryptKeyset );

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* The maximum size of the index data for a user, ~128 bytes, and for the 
   fixed user information */

#define MAX_USERINDEX_SIZE	( 16 + ( KEYID_SIZE * 2 ) + CRYPT_MAX_TEXTSIZE + 8 )
#define MAX_USERINFO_SIZE	MAX_USERINDEX_SIZE

/* The size of the default buffer used to read data from a keyset.  If
   the data is larger than this, a large buffer is allocated dynamically */

#define KEYSET_BUFFERSIZE	1024

/* The different types of userID which we can use for matching purposes */

typedef enum {
	USERID_NONE,		/* No userID type */
	USERID_USERID,		/* User's userID */
	USERID_CREATORID,	/* Creating SO's userID */
	USERID_NAME,		/* User's name */
	USERID_LAST			/* Last possible userID type */
	} USERID_TYPE;

/* Find a user in the user index.  Note that this search implements a flat
   namespace rather than allowing duplicate names created by different SOs
   because when we're looking up a user we don't know which SO they belong
   to until after we've looked them up */

static int findUser( const void *userIndexData, const int userIndexDataLength,
					 const USERID_TYPE idType, const void *userID, 
					 const int userIDlength )
	{
	STREAM stream;
	int fileReference = CRYPT_ERROR_NOTFOUND, status = CRYPT_OK;

	assert( isReadPtr( userIndexData, userIndexDataLength ) );
	assert( ( ( idType > USERID_NONE && idType < USERID_LAST ) && \
			  isReadPtr( userID, userIDlength ) ) || \
			( idType == USERID_NONE && userID == NULL && userIDlength == 0 ) );

	/* Check each entry to make sure that the user name or ID aren't already 
	   present */
	sMemConnect( &stream, userIndexData, userIndexDataLength );
	while( stell( &stream ) < userIndexDataLength )
		{
		BYTE userData[ 128 ];
		long newFileReference;
		int userDataLength;

		readSequence( &stream, NULL );
		if( idType == USERID_USERID )
			readOctetString( &stream, userData, &userDataLength, KEYID_SIZE );
		else
			readUniversal( &stream );
		if( idType == USERID_CREATORID )
			readOctetString( &stream, userData, &userDataLength, KEYID_SIZE );
		else
			readUniversal( &stream );
		if( idType == USERID_NAME )
			readCharacterString( &stream, userData, &userDataLength, 
								 CRYPT_MAX_TEXTSIZE, BER_STRING_UTF8 );
		else
			readUniversal( &stream );
		status = readShortInteger( &stream, &newFileReference );
		if( cryptStatusError( status ) )
			break;
		if( idType == USERID_NONE )
			{
			/* If we're looking for a free file reference and there's one 
			   present thats higher then the existing one, remember the new
			   maximum value */
			if( newFileReference > fileReference )
				fileReference = newFileReference;
			}
		else
			/* Check whether this is the user info we want */
			if( userIDlength == userDataLength && \
				!memcmp( userData, userData, userDataLength ) )
				{
				fileReference = ( int ) newFileReference;
				break;
				}
		}
	sMemDisconnect( &stream );

	return( cryptStatusError( status ) ? status : fileReference );
	}

/* Open a user keyset */

static int openUserKeyset( CRYPT_KEYSET *iUserKeyset, const char *fileName,
						   const int options )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	char userFilePath[ MAX_PATH_LENGTH + 128 ];	/* Protection for Windows */
	int status;

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

	/* Open the given keyset */
	fileBuildCryptlibPath( userFilePath, fileName, 
						   ( options == CRYPT_KEYOPT_READONLY ) ? \
						   BUILDPATH_GETPATH : BUILDPATH_CREATEPATH );
	setMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );
	createInfo.arg2 = options;
	createInfo.strArg1 = userFilePath;
	createInfo.strArgLen1 = strlen( userFilePath );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
							  OBJECT_TYPE_KEYSET );
	if( cryptStatusOK( status ) )
		*iUserKeyset = createInfo.cryptHandle;
	return( status );
	}

/* Read data from a user keyset.  This takes a pointer to a buffer and
   optionally allocates a larger buffer if required, with behaviour
   determined by the overallocSize parameter.  If it's less than zero
   then no attempt to allocate a larger buffer is made, if it's zero
   then a larger buffer is allocated, and if it's larger than zero then
   a buffer of the required size plus the overallocSize value is
   allocated */

static int readUserData( const CRYPT_KEYSET iUserKeyset, 
						 const CRYPT_ATTRIBUTE_TYPE dataType, 
						 void **data, int *dataLength, 
						 const int overallocSize )
	{
	RESOURCE_DATA msgData;
	void *dataPtr = *data;
	int status;

	/* Clear return value */
	*dataLength = 0;

	/* Read the requested data from the keyset, allocating a bigger
	   buffer if required.  When we allocate the buffer we add a caller-
	   specified over-allocation amount to handle any extra data the caller
	   wants to add to the buffer */
	setMessageData( &msgData, NULL, 0 );
	status = krnlSendMessage( iUserKeyset, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, dataType );
	if( cryptStatusError( status ) )
		return( status );
	if( msgData.length > KEYSET_BUFFERSIZE )
		{
		if( overallocSize == CRYPT_ERROR )
			/* Don't try to reallocate the buffer if it's too small, there
			   shouldn't be this much data present */
			return( CRYPT_ERROR_OVERFLOW );
		if( ( dataPtr = clDynAlloc( "readUserData", \
									msgData.length + overallocSize ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		}
	msgData.data = dataPtr;
	status = krnlSendMessage( iUserKeyset, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, dataType );
	if( cryptStatusError( status ) )
		{
		if( dataPtr != *data )
			clFree( "readUserData", dataPtr );
		}
	else
		{
		*data = dataPtr;
		*dataLength = msgData.length;
		}
	return( status );
	}

/* Find the file reference for a given user in the index keyset */

static int findUserFileRef( const USERID_TYPE idType, const BYTE *id, 
							const int idLength )
	{
	CRYPT_KEYSET iUserKeyset;
	BYTE buffer[ KEYSET_BUFFERSIZE ];
	void *bufPtr = buffer;
	int length, status;

	/* Open the index file and read the index entries from it */
	status = openUserKeyset( &iUserKeyset, "index", CRYPT_KEYOPT_READONLY );
	if( cryptStatusError( status ) )
		{
		/* If there's no index file present, we're in the zeroised state,
		   the only valid user is the (implicitly present) primary SO */

⌨️ 快捷键说明

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