📄 cryptdbx.c
字号:
return( CRYPT_ERROR_INCOMPLETE );
/* Items in a cert store can be expired or revoked by never directly
deleted */
if( keysetInfoPtr->keysetDBMS.isCertStore )
unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_PERMISSION );
/* If we've been passed a full issuerAndSerialNumber as a key ID and
the keyset needs an issuerID, convert it */
if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
( keysetInfoPtr->type == KEYSET_DBMS || \
( keysetInfoPtr->type == KEYSET_FILE && \
keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) ) )
{
HASHFUNCTION hashFunction;
int hashSize;
/* Get the hash algorithm information */
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
/* Hash the full iAndS to get an issuerID and use that for the keyID */
hashFunction( NULL, keyIDbuffer, ( BYTE * ) keyID, keyIDlength,
HASH_ALL );
keyIDtype = CRYPT_IKEYID_ISSUERID;
keyID = keyIDbuffer;
keyIDlength = hashSize;
}
/* Delete the key */
status = keysetInfoPtr->deleteItemFunction( keysetInfoPtr,
messageValue, keyIDtype,
keyID, keyIDlength );
if( cryptStatusOK( status ) )
/* The update succeeded, remember that the data in the keyset has
changed */
keysetInfoPtr->isDirty = TRUE;
unlockResourceExit( keysetInfoPtr, status );
}
if( message == RESOURCE_MESSAGE_KEY_GETFIRSTCERT )
{
MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
int status;
assert( getnextcertInfo->keyIDtype != CRYPT_KEYID_NONE && \
getnextcertInfo->keyID != NULL && \
getnextcertInfo->keyIDlength >= 1 );
assert( getnextcertInfo->auxInfo == NULL || \
getnextcertInfo->auxInfoLength == sizeof( int ) );
/* Make sure we can query this keyset type */
if( keysetInfoPtr->getFirstItemFunction == NULL )
unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_NOTAVAIL );
/* Fetch the first cert in a sequence from the keyset */
status = keysetInfoPtr->getFirstItemFunction( keysetInfoPtr,
&getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,
getnextcertInfo->keyIDtype, getnextcertInfo->keyID,
getnextcertInfo->keyIDlength, messageValue,
getnextcertInfo->flags );
unlockResourceExit( keysetInfoPtr, status );
}
if( message == RESOURCE_MESSAGE_KEY_GETNEXTCERT )
{
MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
int status;
assert( getnextcertInfo->keyIDtype == CRYPT_KEYID_NONE && \
getnextcertInfo->keyID == NULL && \
getnextcertInfo->keyIDlength == 0 );
assert( getnextcertInfo->auxInfo == NULL || \
getnextcertInfo->auxInfoLength == sizeof( int ) );
/* Make sure we can query this keyset type */
if( keysetInfoPtr->getFirstItemFunction == NULL )
unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_NOTAVAIL );
/* Fetch the next cert in a sequence from the keyset */
status = keysetInfoPtr->getNextItemFunction( keysetInfoPtr,
&getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,
getnextcertInfo->flags );
unlockResourceExit( keysetInfoPtr, status );
}
if( message == RESOURCE_MESSAGE_KEY_CERTMGMT )
{
MESSAGE_CERTMGMT_INFO *certMgmtInfo = \
( MESSAGE_CERTMGMT_INFO * ) messageDataPtr;
int status;
assert( messageValue >= CRYPT_CERTACTION_CERT_CREATION && \
messageValue <= CRYPT_CERTACTION_LAST_USER );
/* Make sure the access is valid for this keyset type */
if( keysetInfoPtr->certMgmtFunction == NULL )
unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_NOTAVAIL );
/* If we're in the middle of a query, we can't do anything else */
if( keysetInfoPtr->queryInProgress )
return( CRYPT_ERROR_INCOMPLETE );
/* Perform the cert management operation */
status = keysetInfoPtr->certMgmtFunction( keysetInfoPtr,
( certMgmtInfo->cryptCert != CRYPT_UNUSED ) ? \
&certMgmtInfo->cryptCert : NULL, certMgmtInfo->caKey,
certMgmtInfo->request, messageValue );
if( cryptStatusOK( status ) )
/* The update succeeded, remember that the data in the keyset has
changed */
keysetInfoPtr->isDirty = TRUE;
unlockResourceExit( keysetInfoPtr, status );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* Open a keyset. This is a low-level function encapsulated by createKeyset()
and used to manage error exits */
static int openKeyset( CRYPT_KEYSET *iCryptKeyset,
const CRYPT_USER cryptOwner,
const CRYPT_KEYSET_TYPE keysetType,
const char *name, const char *param,
const CRYPT_KEYOPT_TYPE options,
KEYSET_INFO **keysetInfoPtrPtr )
{
KEYSET_INFO *keysetInfoPtr;
const int subType = \
( keysetType == CRYPT_KEYSET_FILE ) ? SUBTYPE_KEYSET_FILE : \
( keysetType == CRYPT_KEYSET_HTTP ) ? SUBTYPE_KEYSET_HTTP : \
( keysetType == CRYPT_KEYSET_LDAP ) ? SUBTYPE_KEYSET_LDAP : \
( keysetType == CRYPT_KEYSET_MYSQL || \
keysetType == CRYPT_KEYSET_ODBC || \
keysetType == CRYPT_KEYSET_DATABASE ) ? SUBTYPE_KEYSET_DBMS : \
SUBTYPE_KEYSET_DBMS_STORE;
int status;
/* Clear the return values */
*iCryptKeyset = CRYPT_ERROR;
*keysetInfoPtrPtr = NULL;
/* Perform general checks which can be done before we create the object */
if( ( subType == SUBTYPE_KEYSET_HTTP && \
options != CRYPT_KEYOPT_READONLY ) || \
( subType == SUBTYPE_KEYSET_LDAP && \
options == CRYPT_KEYOPT_CREATE ) )
/* We can't open an HTTP keyset for anything other than read-only
access, and we can't create an LDAP directory */
return( CRYPT_ERROR_PERMISSION );
/* Wait for any async keyset driver binding to complete */
waitSemaphore( SEMAPHORE_DRIVERBIND );
/* Create the keyset object */
status = krnlCreateObject( ( void ** ) &keysetInfoPtr, cryptOwner,
OBJECT_TYPE_KEYSET, subType,
sizeof( KEYSET_INFO ), 0, 0,
keysetMessageFunction );
if( cryptStatusError( status ) )
return( status );
initResourceLock( keysetInfoPtr );
lockResource( keysetInfoPtr );
*keysetInfoPtrPtr = keysetInfoPtr;
*iCryptKeyset = keysetInfoPtr->objectHandle = status;
keysetInfoPtr->ownerHandle = cryptOwner;
keysetInfoPtr->options = options;
/* If it's a flat-file keyset, open a handle to it */
if( keysetType == CRYPT_KEYSET_FILE )
{
int openMode;
keysetInfoPtr->type = KEYSET_FILE;
/* Remember the key file's name */
if( strlen( name ) > MAX_PATH_LENGTH - 1 )
return( CRYPT_ARGERROR_STR1 );
strcpy( keysetInfoPtr->keysetFile.fileName, name );
/* If the file is read-only, put the keyset into read-only mode. We
have to perform this test before we try to open it because some
OS's don't allow a file to be reopened for write access when it's
already open, and it's better to have it appear read-only than
not at all */
if( fileReadonly( name ) )
{
/* If we want to create a new file, we can't do it if we don't
have write permission */
if( options == CRYPT_KEYOPT_CREATE )
return( CRYPT_ERROR_PERMISSION );
/* Open the file in readonly mode */
keysetInfoPtr->options = CRYPT_KEYOPT_READONLY;
openMode = FILE_READ;
}
else
/* If we're creating the file, open it in write-only mode. Since
we'll (presumably) be storing private keys in it, we mark it
as both private (owner-access-only ACL) and sensitive (store
in secure storage if possible) */
if( options == CRYPT_KEYOPT_CREATE )
openMode = FILE_WRITE | FILE_EXCLUSIVE_ACCESS | \
FILE_PRIVATE | FILE_SENSITIVE;
else
/* Open it for read or read/write depending on whether the
readonly flag is set */
openMode = ( options != CRYPT_KEYOPT_READONLY ) ? \
FILE_READ | FILE_WRITE : FILE_READ;
if( options == CRYPT_IKEYOPT_EXCLUSIVEACCESS )
openMode |= FILE_EXCLUSIVE_ACCESS;
/* Pre-open the file containing the keyset. This initially opens it
in read-only mode for auto-detection of the file type so we can
check for various problems (eg trying to open a non-writeable file
format type for write access) */
status = sFileOpen( &keysetInfoPtr->keysetFile.stream, name,
FILE_READ );
if( cryptStatusError( status ) )
{
/* The file doesn't exit, if the create flag isn't set return an
error */
if( options != CRYPT_KEYOPT_CREATE )
return( status );
/* Try and create a new file */
status = sFileOpen( &keysetInfoPtr->keysetFile.stream, name,
openMode );
if( cryptStatusError( status ) )
return( status );
keysetInfoPtr->subType = KEYSET_SUBTYPE_PKCS15;
setAccessMethodPKCS15( keysetInfoPtr );
}
else
{
/* The file exists, get its type */
keysetInfoPtr->subType = getKeysetType( &keysetInfoPtr->keysetFile.stream );
if( keysetInfoPtr->subType == KEYSET_SUBTYPE_ERROR )
/* If we're creating a new keyset and there's already
something there, make it look like a cryptlib keyset so
it'll get overwritten later */
if( options == CRYPT_KEYOPT_CREATE )
keysetInfoPtr->subType = KEYSET_SUBTYPE_PKCS15;
else
{
/* "It doesn't look like anything from here" */
sFileClose( &keysetInfoPtr->keysetFile.stream );
return( CRYPT_ERROR_BADDATA );
}
/* Set up the access information for the file */
switch( keysetInfoPtr->subType )
{
case KEYSET_SUBTYPE_PKCS12:
setAccessMethodPKCS12( keysetInfoPtr );
break;
case KEYSET_SUBTYPE_PKCS15:
setAccessMethodPKCS15( keysetInfoPtr );
break;
case KEYSET_SUBTYPE_PGP_PUBLIC:
case KEYSET_SUBTYPE_PGP_PRIVATE:
setAccessMethodPGP( keysetInfoPtr );
break;
default:
assert( NOTREACHED );
}
/* If it's a cryptlib keyset we can open it in any mode */
if( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 )
{
/* If we're opening it something other than readonly mode,
reopen it in that mode */
if( openMode != FILE_READ )
{
sFileClose( &keysetInfoPtr->keysetFile.stream );
status = sFileOpen( &keysetInfoPtr->keysetFile.stream,
name, openMode );
if( cryptStatusError( status ) )
return( status ); /* Exit with file closed */
}
}
else
/* If it's a non-cryptlib keyset we can't open it for
anything other than read-only access */
if( options != CRYPT_KEYOPT_READONLY )
status = CRYPT_ERROR_PERMISSION;
}
if( cryptStatusOK( status ) )
status = keysetInfoPtr->initFunction( keysetInfoPtr, NULL, NULL,
options );
if( cryptStatusError( status ) )
{
sFileClose( &keysetInfoPtr->keysetFile.stream );
return( status );
}
if( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 && \
openMode == FILE_READ )
/* If we've got the keyset open in read-only mode we don't need
to touch it again so we can close the file stream */
sFileClose( &keysetInfoPtr->keysetFile.stream );
keysetInfoPtr->isOpen = TRUE;
if( options == CRYPT_KEYOPT_CREATE )
keysetInfoPtr->isEmpty = TRUE;
return( CRYPT_OK );
}
/* It's a specific type of keyset, set up the access information for it
and connect to it */
switch( keysetType )
{
case CRYPT_KEYSET_MYSQL:
case CRYPT_KEYSET_ODBC:
case CRYPT_KEYSET_DATABASE:
case CRYPT_KEYSET_MYSQL_STORE:
case CRYPT_KEYSET_ODBC_STORE:
case CRYPT_KEYSET_DATABASE_STORE:
keysetInfoPtr->type = KEYSET_DBMS;
status = setAccessMethodDBMS( keysetInfoPtr, keysetType );
break;
case CRYPT_KEYSET_HTTP:
keysetInfoPtr->type = KEYSET_HTTP;
status = setAccessMethodHTTP( keysetInfoPtr );
break;
case CRYPT_KEYSET_LDAP:
keysetInfoPtr->type = KEYSET_LDAP;
status = setAccessMethodLDAP( keysetInfoPtr );
break;
default:
assert( NOTREACHED );
}
if( cryptStatusOK( status ) )
{
assert( keysetInfoPtr->initFunction != NULL );
assert( keysetInfoPtr->getItemFunction != NULL );
status = keysetInfoPtr->initFunction( keysetInfoPtr, name, param,
options );
}
if( cryptStatusError( status ) )
return( status );
keysetInfoPtr->isOpen = TRUE;
if( options == CRYPT_KEYOPT_CREATE )
keysetInfoPtr->isEmpty = TRUE;
return( status );
}
/* Create a keyset object */
int createKeyset( MESSAGE_CREATEOBJECT_INFO *createInfo,
const void *auxDataPtr, const int auxValue )
{
CRYPT_KEYSET iCryptKeyset;
const CRYPT_KEYSET_TYPE keysetType = createInfo->arg1;
const CRYPT_KEYOPT_TYPE options = createInfo->arg2;
KEYSET_INFO *keysetInfoPtr;
char nameBuffer[ MAX_ATTRIBUTE_SIZE + 1 ];
char argBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *argBufPtr = NULL;
int initStatus, status;
assert( auxDataPtr == NULL );
assert( auxValue == 0 );
/* Perform basic error checking */
if( keysetType <= CRYPT_KEYSET_NONE || keysetType >= CRYPT_KEYSET_LAST )
return( CRYPT_ARGERROR_NUM1 );
if( createInfo->strArgLen1 < 2 || \
createInfo->strArgLen1 >= MAX_ATTRIBUTE_SIZE )
return( CRYPT_ARGERROR_STR1 );
memcpy( nameBuffer, createInfo->strArg1, createInfo->strArgLen1 );
nameBuffer[ createInfo->strArgLen1 ] = '\0';
if( createInfo->strArgLen2 > 0 )
{
if( createInfo->strArgLen2 < 2 || \
createInfo->strArgLen2 >= MAX_ATTRIBUTE_SIZE )
return( CRYPT_ARGERROR_STR2 );
memcpy( argBuffer, createInfo->strArg2, createInfo->strArgLen1 );
argBuffer[ createInfo->strArgLen1 ] = '\0';
argBufPtr = argBuffer;
}
if( options < CRYPT_KEYOPT_NONE || options >= CRYPT_KEYOPT_LAST )
/* CRYPT_KEYOPT_NONE is a valid setting for this parameter */
return( CRYPT_ARGERROR_NUM2 );
/* Pass the call on to the lower-level open function */
initStatus = openKeyset( &iCryptKeyset, createInfo->cryptOwner,
keysetType, nameBuffer, argBufPtr, options,
&keysetInfoPtr );
if( keysetInfoPtr == NULL )
return( initStatus ); /* Create object failed, return immediately */
if( cryptStatusError( initStatus ) )
/* The keyset open failed, make sure the object gets destroyed when
we notify the kernel that the setup process is complete */
krnlSendNotifier( iCryptKeyset, RESOURCE_IMESSAGE_DESTROY );
/* We've finished setting up the object-type-specific info, tell the
kernel the object is ready for use */
unlockResource( keysetInfoPtr );
status = krnlSendMessage( iCryptKeyset, RESOURCE_IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
return( cryptStatusError( initStatus ) ? initStatus : status );
createInfo->cryptHandle = iCryptKeyset;
return( CRYPT_OK );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -