📄 cryptusr.c
字号:
writeSequence( &stream, 2 * sizeofObject( KEYID_SIZE ) + \
sizeofObject( userInfoPtr->userNameLength ) + \
sizeofShortInteger( newReference ) );
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 );
writeShortInteger( &stream, newReference, DEFAULT_TAG );
userInfoLength = stell( &stream );
sMemDisconnect( &stream );
if( lastPos < *userIndexDataLength )
memmove( userIndexData + lastPos + userInfoLength,
userIndexData + lastPos, *userIndexDataLength - lastPos );
memcpy( userIndexData + lastPos, userInfoBuffer, userInfoLength );
*userIndexDataLength += userInfoLength;
return( newReference );
}
/* Read a user's info from a user keyset and verify it using the creating
SO's key */
static int getCheckUserInfo( USER_FILE_INFO *userFileInfo, const int fileRef )
{
CRYPT_ALGO hashAlgo;
CRYPT_KEYSET iUserKeyset;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_KEYMGMT_INFO getkeyInfo;
STREAM stream;
BYTE buffer[ KEYSET_BUFFERSIZE ];
void *bufPtr = buffer, *hashDataPtr, *signaturePtr;
char userFileName[ 16 ];
int soFileRef, hashDataLength, signatureLength, length, enumValue, status;
/* Clear return values */
memset( userFileInfo, 0, sizeof( USER_FILE_INFO ) );
/* Open the index keyset and read the user info from it */
sprintf( userFileName, "u%06x", fileRef );
status = openUserKeyset( &iUserKeyset, userFileName,
CRYPT_KEYOPT_READONLY );
if( cryptStatusError( status ) )
return( status );
status = readUserData( iUserKeyset, CRYPT_IATTRIBUTE_USERINFO,
&bufPtr, &length, CRYPT_ERROR );
krnlSendNotifier( iUserKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
return( status );
/* Burrow into the user info to get the information we need. We do it
this way rather than using envelopes because we don't need the full
generality of the enveloping process (we know exactly what data to
expect) and to avoid the overhead of de-enveloping data every time a
user logs in */
sMemConnect( &stream, buffer, length );
readSequence( &stream, NULL ); /* Outer wrapper */
readUniversal( &stream ); /* ContentType OID */
readConstructed( &stream, NULL, 0 ); /* Content */
readSequence( &stream, NULL );
readUniversal( &stream ); /* Version */
readSet( &stream, NULL ); /* DigestAlgorithms */
readAlgoID( &stream, &hashAlgo );
readSequence( &stream, NULL ); /* EncapContentInfo */
readUniversal( &stream ); /* ContentType OID */
readConstructed( &stream, NULL, 0 ); /* Content type wrapper */
status = readGenericHole( &stream, &hashDataLength );
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( status );
}
hashDataPtr = sMemBufPtr( &stream );
/* Read the user info */
readSequence( &stream, NULL );
readEnumerated( &stream, &enumValue );
userFileInfo->type = enumValue;
readOctetString( &stream, userFileInfo->userID, &length, KEYID_SIZE );
readOctetString( &stream, userFileInfo->creatorID, &length, KEYID_SIZE );
status = readOctetStringTag( &stream, userFileInfo->userName,
&userFileInfo->userNameLength,
CRYPT_MAX_TEXTSIZE, BER_STRING_UTF8 );
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( status );
}
/* Read the signature */
status = readSet( &stream, &signatureLength );
signaturePtr = sMemBufPtr( &stream );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
return( status );
/* Open the SO keyset and read the SO public key from it */
status = soFileRef = \
findUserFileRef( USERID_USERID, userFileInfo->creatorID, KEYID_SIZE );
if( cryptStatusOK( status ) )
{
sprintf( userFileName, "u%06x", soFileRef );
status = openUserKeyset( &iUserKeyset, userFileName,
CRYPT_KEYOPT_READONLY );
}
if( cryptStatusError( status ) )
return( status );
setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_ID,
userFileInfo->creatorID, KEYID_SIZE, NULL, 0,
KEYMGMT_FLAG_NONE );
status = krnlSendMessage( iUserKeyset, RESOURCE_IMESSAGE_KEY_GETKEY,
&getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );
krnlSendNotifier( iUserKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
return( status );
/* Hash the signed data and verify the signature using the SO key */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
{
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_CTX_HASH,
hashDataPtr, hashDataLength );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_CTX_HASH, hashDataPtr, 0 );
if( cryptStatusOK( status ) )
status = iCryptCheckSignatureEx( signaturePtr, signatureLength,
getkeyInfo.cryptHandle,
createInfo.cryptHandle, NULL );
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
}
krnlSendNotifier( getkeyInfo.cryptHandle, RESOURCE_IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
return( status );
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/* MAC (???) using password - needs PKCS #15 changes */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
if( cryptStatusError( status ) )
return( status );
return( status );
}
/* Create an SO private key and write it to the user keyset */
static int createSOKey( const CRYPT_KEYSET iUserKeyset,
USER_INFO *userInfoPtr, const char *password,
const int passwordLength )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
const int keyLength = /*128*/64;
const int actionPerms = MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGN,
ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGCHECK,
ACTION_PERM_NONE_EXTERNAL );
int status;
#ifndef NDEBUG
/* Warn that we're using a debug mode for now. The user management code
isn't complete yet so this isn't a problem */
puts( "Kludging SO key size to 512 bits." );
#endif /* NDEBUG */
/* Create the SO private key, making it internal and signature-only */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RSA );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
setResourceData( &msgData, userInfoPtr->userName,
userInfoPtr->userNameLength );
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
( int * ) &keyLength, CRYPT_CTXINFO_KEYSIZE );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_CTX_GENKEY, NULL, FALSE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
( int * ) &actionPerms,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
/* Add the newly-created private key to the keyset */
setResourceData( &msgData, ( void * ) userInfoPtr->userID,
KEYID_SIZE );
status = krnlSendMessage( iUserKeyset, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERID );
if( cryptStatusOK( status ) )
{
MESSAGE_KEYMGMT_INFO setkeyInfo;
setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,
( void * ) password, passwordLength,
KEYMGMT_FLAG_NONE );
setkeyInfo.cryptHandle = createInfo.cryptHandle;
status = krnlSendMessage( iUserKeyset, RESOURCE_IMESSAGE_KEY_SETKEY,
&setkeyInfo, KEYMGMT_ITEM_PRIVATEKEY );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
userInfoPtr->iCryptContext = createInfo.cryptHandle;
return( CRYPT_OK );
}
/* Create a CA secret key and write it to the user keyset */
static int createCAKey( const CRYPT_KEYSET iUserKeyset,
USER_INFO *userInfoPtr, const char *password,
const int passwordLength )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
const int actionPerms = MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT,
ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT,
ACTION_PERM_NONE_EXTERNAL );
int status;
/* Create the CA secret key, making it internal-only */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_3DES );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
setResourceData( &msgData, userInfoPtr->userID, KEYID_SIZE );
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_CTX_GENKEY, NULL, FALSE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
( int * ) &actionPerms,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
/* Add the newly-created secret key to the keyset */
setResourceData( &msgData, ( void * ) userInfoPtr->userID,
KEYID_SIZE );
status = krnlSendMessage( iUserKeyset, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERID );
if( cryptStatusOK( status ) )
{
MESSAGE_KEYMGMT_INFO setkeyInfo;
setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,
( void * ) password, passwordLength,
KEYMGMT_FLAG_NONE );
setkeyInfo.cryptHandle = createInfo.cryptHandle;
status = krnlSendMessage( iUserKeyset, RESOURCE_IMESSAGE_KEY_SETKEY,
&setkeyInfo, KEYMGMT_ITEM_SECRETKEY );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
return( CRYPT_OK );
}
/* 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 ];
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,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
return( status );
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
( int * ) &minBufferSize, CRYPT_ATTRIBUTE_BUFFERSIZE );
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
&userInfoLength, CRYPT_ENVINFO_DATASIZE );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
( void * ) &iSignContext,
CRYPT_ENVINFO_SIGNATURE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
/* Push in the data and pop the signed result */
setResourceData( &msgData, userInfoBuffer, userInfoLength );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_ENV_PUSHDATA, &msgData, 0 );
if( cryptStatusOK( status ) )
{
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_ENV_PUSHDATA, &msgData, 0 );
}
if( cryptStatusOK( status ) )
{
setResourceData( &msgData, userInfoBuffer, 1024 );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_ENV_POPDATA, &msgData, 0 );
}
krnlSendNotifier( createInfo.cryptHandle, RESOURCE_IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
return( status );
/* Add the user ID and SO-signed user info to the keyset */
status = krnlSendMessage( iUserKeyset, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERINFO );
zeroise( userInfoBuffer, 1024 );
if( cryptStatusOK( status ) )
{
setResourceData( &msgData, ( void * ) userInfoPtr->userID,
KEYID_SIZE );
status = krnlSendMessage( iUserKeyset, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_USERID );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -