📄 cryptusr.c
字号:
}
return( CRYPT_OK );
}
#endif /* 0 */
/* Sign the user info and write it to the user keyset */
static int writeUserInfo( const CRYPT_KEYSET iUserKeyset,
const USER_INFO *userInfoPtr,
const CRYPT_CONTEXT iSignContext )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
STREAM stream;
BYTE userInfoBuffer[ 1024 ];
static const int minBufferSize = MIN_BUFFER_SIZE;
int userInfoLength, status;
/* Write the user information to a memory buffer */
sMemOpen( &stream, userInfoBuffer, MAX_USERINFO_SIZE );
writeSequence( &stream, sizeofShortInteger( userInfoPtr->type ) + \
2 * sizeofObject( KEYID_SIZE ) + \
sizeofObject( userInfoPtr->userNameLength ) );
writeEnumerated( &stream, userInfoPtr->type, DEFAULT_TAG );
writeOctetString( &stream, userInfoPtr->userID, KEYID_SIZE, DEFAULT_TAG );
writeOctetString( &stream, userInfoPtr->creatorID, KEYID_SIZE, DEFAULT_TAG );
writeCharacterString( &stream, userInfoPtr->userName,
userInfoPtr->userNameLength, BER_STRING_UTF8 );
userInfoLength = stell( &stream );
sMemDisconnect( &stream );
/* Create a cryptlib envelope to sign the data. This is kind of
heavyweight, but it's OK because we rarely create new users and it
saves having to hand-assemble the data like the PKCS #15 code does */
setMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_CRYPTLIB );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
return( status );
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
( int * ) &minBufferSize, CRYPT_ATTRIBUTE_BUFFERSIZE );
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
&userInfoLength, CRYPT_ENVINFO_DATASIZE );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE,
( void * ) &iSignContext,
CRYPT_ENVINFO_SIGNATURE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Push in the data and pop the signed result */
setMessageData( &msgData, userInfoBuffer, userInfoLength );
status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_ENV_PUSHDATA, &msgData, 0 );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, userInfoBuffer, 1024 );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_ENV_POPDATA, &msgData, 0 );
}
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
return( status );
/* Add the user ID and SO-signed user info to the keyset */
status = krnlSendMessage( iUserKeyset, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERINFO );
zeroise( userInfoBuffer, 1024 );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) userInfoPtr->userID,
KEYID_SIZE );
status = krnlSendMessage( iUserKeyset, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERID );
}
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 */
if( status == CRYPT_ERROR_NOTFOUND )
return( CRYPT_OK );
/* If there's something there but it's damaged, delete it so we can
start again */
if( status == CRYPT_ERROR_BADDATA )
{
char userFilePath[ MAX_PATH_LENGTH + 128 ]; /* Protection for Windows */
fileBuildCryptlibPath( userFilePath, "index", BUILDPATH_GETPATH );
fileErase( userFilePath );
return( CRYPT_OK );
}
return( status );
}
status = readUserData( iIndexKeyset, CRYPT_IATTRIBUTE_USERINDEX,
&bufPtr, &length, 0 );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
clFree( "zeroiseUsers", 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%06lx", fileRef );
fileBuildCryptlibPath( userFilePath, userFileName,
BUILDPATH_GETPATH );
status = sFileOpen( &fileStream, userFilePath,
FILE_READ | FILE_WRITE | FILE_EXCLUSIVE_ACCESS );
if( cryptStatusError( status ) )
continue;
fileClearToEOF( &fileStream );
sFileClose( &fileStream );
fileErase( userFilePath );
}
sMemDisconnect( &stream );
if( bufPtr != buffer )
clFree( "zeroiseUsers", bufPtr );
/* Erase the index file by setting zero-length user index info, which
results in an empty keyset which is erased on close */
setMessageData( &msgData, ( void * ) zeroUserData, 2 );
status = krnlSendMessage( iIndexKeyset, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERINDEX );
krnlSendNotifier( iIndexKeyset, 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 indicates that the file doesn't exist, try and create it
instead */
status = openUserKeyset( &iIndexKeyset, "index",
CRYPT_IKEYOPT_EXCLUSIVEACCESS );
if( status == CRYPT_ERROR_NOTFOUND )
{
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 that 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, IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
clFree( "createUserKeyset", 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, IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
clFree( "createUserKeyset", bufPtr );
return( CRYPT_ERROR_DUPLICATE );
}
/* Make sure that the userID is unique */
do
{
status = findUser( bufPtr, length, USERID_USERID,
userInfoPtr->userID, KEYID_SIZE );
if( !cryptStatusError( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, userInfoPtr->userID, KEYID_SIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM_NONCE );
}
}
while( !cryptStatusError( status ) );
/* Locate a new unused file reference that we can use */
fileRef = findUser( bufPtr, length, USERID_NONE, NULL, 0 );
}
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, IMESSAGE_DECREFCOUNT );
if( bufPtr != buffer )
clFree( "createUserKeyset", bufPtr );
return( status );
}
/* Update the index file */
status = insertIndexEntry( userInfoPtr, bufPtr, &length );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, bufPtr, length );
status = krnlSendMessage( iIndexKeyset, 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, IMESSAGE_DECREFCOUNT );
else
{
userInfoPtr->fileRef = fileRef;
*iCreatedKeyset = iUserKeyset;
}
krnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );
/* Clean up */
if( bufPtr != buffer )
clFree( "createUserKeyset", 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 ) )
{
RESOURCE_DATA msgData;
/* 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 */
setMessageData( &msgData, userInfoPtr->userID, KEYID_SIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( cryptStatusOK( status ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -