📄 trustmgr.c
字号:
/* Add and delete a trust entry */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int addEntry( INOUT TYPECAST( TRUST_INFO ** ) void *trustInfoPtrPtr,
IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,
IN_BUFFER_OPT( certObjectLength ) const void *certObject,
IN_LENGTH_SHORT_Z const int certObjectLength )
{
TRUST_INFO **trustInfoIndex = ( TRUST_INFO ** ) trustInfoPtrPtr;
TRUST_INFO *newElement, *trustInfoCursor, *trustInfoLast;
BYTE sHash[ HASH_DATA_SIZE + 8 ];
BOOLEAN recreateCert = FALSE;
int sCheck, trustInfoEntry, iterationCount, status;
assert( isWritePtr( trustInfoPtrPtr, \
sizeof( TRUST_INFO * ) * TRUSTINFO_SIZE ) );
assert( ( certObject == NULL && certObjectLength == 0 && \
isHandleRangeValid( iCryptCert ) ) || \
( isReadPtr( certObject, certObjectLength ) && \
iCryptCert == CRYPT_UNUSED ) );
REQUIRES( ( certObject == NULL && certObjectLength == 0 && \
isHandleRangeValid( iCryptCert ) ) || \
( certObject != NULL && \
certObjectLength >= MIN_CRYPT_OBJECTSIZE && \
certObjectLength < MAX_INTLENGTH_SHORT && \
iCryptCert == CRYPT_UNUSED ) );
/* If we're adding a certificate, check whether it has a context
attached and if it does, whether it's a public-key context. If
there's no context attached (it's a data-only certificate) or the
attached context is a private-key context (which we don't want to
leave hanging around in memory, or which could be in a removable
crypto device) we don't try and use the certificate but instead add
the certificate data and then later re-instantiate a new certificate
with attached public-key context if required */
if( certObject == NULL )
{
CRYPT_CONTEXT iCryptContext;
status = krnlSendMessage( iCryptCert, IMESSAGE_GETDEPENDENT,
&iCryptContext, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
{
/* There's no context associated with this certificate, we'll
have to recreate it later */
recreateCert = TRUE;
}
else
{
status = krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_PRIVATE );
if( cryptStatusOK( status ) )
{
/* The context associated with the certificate is a private-
key context, recreate it later as a public-key context */
recreateCert = TRUE;
}
}
}
/* Get the ID information for the certificate */
if( certObject == NULL )
{
DYNBUF subjectDB;
/* Generate the checksum and hash of the certificate object's
subject name and key ID */
status = dynCreate( &subjectDB, iCryptCert,
CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
return( status );
sCheck = checksumData( dynData( subjectDB ),
dynLength( subjectDB ) );
hashData( sHash, HASH_DATA_SIZE, dynData( subjectDB ),
dynLength( subjectDB ) );
#if 0 /* sKID lookup isn't used at present */
DYNBUF subjectKeyDB;
status = dynCreate( &subjectKeyDB, iCryptCert,
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
if( cryptStatusOK( status ) )
{
kCheck = checksumData( dynData( subjectKeyDB ),
dynLength( subjectKeyDB ) );
hashData( kHash, HASH_DATA_SIZE, dynData( subjectKeyDB ),
dynLength( subjectKeyDB ) );
dynDestroy( &subjectKeyDB );
}
#endif /* 0 */
dynDestroy( &subjectDB );
}
else
{
void *subjectDNptr;
int subjectDNsize;
/* Get the ID information from the encoded certificate */
status = getCertIdInfo( certObject, certObjectLength,
&subjectDNptr, &subjectDNsize );
ENSURES( cryptStatusOK( status ) );
/* Generate the checksum and hash of the encoded certificate's
subject name and key ID */
sCheck = checksumData( subjectDNptr, subjectDNsize );
hashData( sHash, HASH_DATA_SIZE, subjectDNptr, subjectDNsize );
#if 0 /* sKID lookup isn't used at present */
kCheck = checksumData( subjectKeyIDptr, subjectKeyIDsize );
hashData( kHash, HASH_DATA_SIZE, subjectKeyIDptr, subjectKeyIDsize );
#endif /* 0 */
}
/* Find the insertion point and make sure that this entry isn't already
present */
trustInfoEntry = sCheck & ( TRUSTINFO_SIZE - 1 );
ENSURES( trustInfoEntry >= 0 && trustInfoEntry < TRUSTINFO_SIZE );
for( trustInfoCursor = trustInfoLast = trustInfoIndex[ trustInfoEntry ], \
iterationCount = 0; \
trustInfoCursor != NULL && \
iterationCount < FAILSAFE_ITERATIONS_MED; \
trustInfoCursor = trustInfoCursor->next, iterationCount++ )
{
/* Perform a quick check using a checksum of the name to weed out
most entries */
if( trustInfoCursor->sCheck == sCheck && \
!memcmp( trustInfoCursor->sHash, sHash, HASH_DATA_SIZE ) )
return( CRYPT_ERROR_DUPLICATE );
trustInfoLast = trustInfoCursor;
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
trustInfoCursor = trustInfoLast;
/* Allocate memory for the new element and copy the information across */
if( ( newElement = ( TRUST_INFO * ) \
clAlloc( "addEntry", sizeof( TRUST_INFO ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( newElement, 0, sizeof( TRUST_INFO ) );
newElement->sCheck = sCheck;
memcpy( newElement->sHash, sHash, HASH_DATA_SIZE );
if( certObject != NULL || recreateCert )
{
DYNBUF certDB;
int objectLength = certObjectLength;
/* If we're using the data from an existing certificate object we
need to extract the encoded data */
if( recreateCert )
{
/* Get the encoded certificate */
status = dynCreateCert( &certDB, iCryptCert,
CRYPT_CERTFORMAT_CERTIFICATE );
if( cryptStatusError( status ) )
{
clFree( "addEntry", newElement );
return( status );
}
certObject = dynData( certDB );
objectLength = dynLength( certDB );
}
/* Remember the trusted certificate data for later use */
if( ( newElement->certObject = clAlloc( "addEntry",
objectLength ) ) == NULL )
{
clFree( "addEntry", newElement );
if( recreateCert )
dynDestroy( &certDB );
return( CRYPT_ERROR_MEMORY );
}
memcpy( newElement->certObject, certObject, objectLength );
newElement->certObjectLength = objectLength;
newElement->iCryptCert = CRYPT_ERROR;
/* Clean up */
if( recreateCert )
dynDestroy( &certDB );
}
else
{
/* The trusted key exists as a standard certificate with a public-
key context attached, remember it for later */
krnlSendNotifier( iCryptCert, IMESSAGE_INCREFCOUNT );
newElement->iCryptCert = iCryptCert;
}
/* Add the new entry to the list */
if( trustInfoCursor == NULL )
trustInfoIndex[ trustInfoEntry ] = newElement;
else
trustInfoCursor->next = newElement;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int addTrustEntry( INOUT TYPECAST( TRUST_INFO ** ) void *trustInfoPtrPtr,
IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,
IN_BUFFER_OPT( certObjectLength ) const void *certObject,
IN_LENGTH_SHORT_Z const int certObjectLength,
const BOOLEAN addSingleCert )
{
BOOLEAN seenNonDuplicate = FALSE;
int iterationCount = 0, status;
assert( isWritePtr( trustInfoPtrPtr, \
sizeof( TRUST_INFO * ) * TRUSTINFO_SIZE ) );
assert( ( certObject == NULL && certObjectLength == 0 && \
isHandleRangeValid( iCryptCert ) ) || \
( isReadPtr( certObject, certObjectLength ) && \
iCryptCert == CRYPT_UNUSED ) );
REQUIRES( ( certObject == NULL && certObjectLength == 0 && \
isHandleRangeValid( iCryptCert ) ) || \
( certObject != NULL && \
certObjectLength >= MIN_CRYPT_OBJECTSIZE && \
certObjectLength < MAX_INTLENGTH_SHORT && \
iCryptCert == CRYPT_UNUSED ) );
/* If we're adding encoded certificate data we can add it directly */
if( certObject != NULL )
{
return( addEntry( trustInfoPtrPtr, CRYPT_UNUSED, certObject,
certObjectLength ) );
}
/* Add the certificate/each certificate in the trust list */
status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusError( status ) )
return( status );
if( !addSingleCert )
{
/* It's a trust list, move to the start of the list */
status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
if( cryptStatusError( status ) )
{
( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_LOCKED );
return( status );
}
}
do
{
/* An item being added may already be present, however we can't fail
immediately because what's being added may be a chain containing
further certificates so we keep track of whether we've
successfully added at least one item and clear data duplicate
errors */
status = addEntry( trustInfoPtrPtr, iCryptCert, NULL, 0 );
if( status == CRYPT_OK )
seenNonDuplicate = TRUE;
else
{
if( status == CRYPT_ERROR_DUPLICATE )
status = CRYPT_OK;
}
}
while( cryptStatusOK( status ) && !addSingleCert && \
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORNEXT,
CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusOK( status ) && !seenNonDuplicate )
{
/* There were no new certificates to add present, return an already-
initialised error */
status = CRYPT_ERROR_INITED;
}
return( status );
}
STDC_NONNULL_ARG( ( 1, 2 ) ) \
void deleteTrustEntry( INOUT TYPECAST( TRUST_INFO ** ) void *trustInfoPtrPtr,
INOUT TYPECAST( TRUST_INFO * ) void *entryToDeletePtr )
{
TRUST_INFO **trustInfoIndex = ( TRUST_INFO ** ) trustInfoPtrPtr;
TRUST_INFO *entryToDelete = ( TRUST_INFO * ) entryToDeletePtr, *prevInfoPtr;
const int trustInfoEntry = entryToDelete->sCheck & ( TRUSTINFO_SIZE - 1 );
assert( isWritePtr( trustInfoPtrPtr, \
sizeof( TRUST_INFO * ) * TRUSTINFO_SIZE ) );
assert( isWritePtr( entryToDeletePtr, sizeof( TRUST_INFO ) ) );
REQUIRES_V( trustInfoEntry >= 0 && trustInfoEntry < TRUSTINFO_SIZE );
/* Unlink the trust information index */
prevInfoPtr = trustInfoIndex[ trustInfoEntry ];
ENSURES_V( prevInfoPtr != NULL );
if( prevInfoPtr == entryToDelete )
{
/* Unlink from the start of the list */
trustInfoIndex[ trustInfoEntry ] = entryToDelete->next;
}
else
{
int iterationCount;
/* Unlink from the middle/end of the list */
for( iterationCount = 0;
prevInfoPtr->next != entryToDelete && \
iterationCount < FAILSAFE_ITERATIONS_MED;
prevInfoPtr = prevInfoPtr->next, iterationCount++ )
{
ENSURES_V( prevInfoPtr != NULL );
}
ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_MED );
prevInfoPtr->next = entryToDelete->next;
}
/* Free the trust information entry */
if( entryToDelete->iCryptCert != CRYPT_ERROR )
krnlSendNotifier( entryToDelete->iCryptCert, IMESSAGE_DECREFCOUNT );
if( entryToDelete->certObject != NULL )
{
zeroise( entryToDelete->certObject, entryToDelete->certObjectLength );
clFree( "deleteTrustEntry", entryToDelete->certObject );
}
memset( entryToDelete, 0, sizeof( TRUST_INFO ) );
clFree( "deleteTrustEntry", entryToDelete );
}
/****************************************************************************
* *
* Init/Shut down Trusted Certificate Information *
* *
****************************************************************************/
/* Initialise and shut down the trust information */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initTrustInfo( OUT_PTR TYPECAST( TRUST_INFO ** ) void **trustInfoPtrPtr )
{
TRUST_INFO *trustInfoIndex;
assert( isWritePtr( trustInfoPtrPtr, sizeof( void * ) ) );
/* Initialise the trust information table */
if( ( trustInfoIndex = \
clAlloc( "initTrustInfo", TRUSTINFO_SIZE * \
sizeof( TRUST_INFO * ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( trustInfoIndex, 0, sizeof( TRUST_INFO * ) * TRUSTINFO_SIZE );
*trustInfoPtrPtr = trustInfoIndex;
return( CRYPT_OK );
}
STDC_NONNULL_ARG( ( 1 ) ) \
void endTrustInfo( INOUT TYPECAST( TRUST_INFO ** ) void *trustInfoPtrPtr )
{
TRUST_INFO **trustInfoIndex = ( TRUST_INFO ** ) trustInfoPtrPtr;
int i;
assert( isWritePtr( trustInfoPtrPtr, \
sizeof( TRUST_INFO * ) * TRUSTINFO_SIZE ) );
/* Destroy the chain of items at each table position */
for( i = 0; i < TRUSTINFO_SIZE; i++ )
{
TRUST_INFO *trustInfoCursor;
int iterationCount;
/* Destroy any items in the list */
for( trustInfoCursor = trustInfoIndex[ i ], iterationCount = 0;
trustInfoCursor != NULL && \
iterationCount < FAILSAFE_ITERATIONS_MED; iterationCount++ )
{
TRUST_INFO *itemToFree = trustInfoCursor;
trustInfoCursor = trustInfoCursor->next;
deleteTrustEntry( trustInfoIndex, itemToFree );
}
ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_MED );
}
memset( trustInfoIndex, 0, TRUSTINFO_SIZE * sizeof( TRUST_INFO * ) );
clFree( "endTrustInfo", trustInfoIndex );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -