📄 cryptkey.c
字号:
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 + -