📄 dev_fort.c
字号:
hFortezza = NULL_HINSTANCE;
return;
}
/* Initialise the Fortezza library */
if( pCI_Initialize( &noSockets ) != CI_OK )
{
/* Free the library reference and reset the handle */
FreeLibrary( hFortezza );
hFortezza = NULL_HINSTANCE;
}
}
void deviceEndFortezza( void )
{
if( hFortezza != NULL_HINSTANCE )
{
pCI_Terminate();
FreeLibrary( hFortezza );
}
hFortezza = NULL_HINSTANCE;
}
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Map a Fortezza-specific error to a cryptlib error */
static int mapError( const int errorCode, const int defaultError )
{
switch( errorCode )
{
case CI_OK:
return( CRYPT_OK );
case CI_NO_CARD:
case CI_BAD_CARD:
return( CRYPT_ERROR_SIGNALLED );
case CI_INV_STATE:
case CI_NO_IV:
case CI_NO_KEY:
return( CRYPT_ERROR_NOTINITED );
case CI_EXEC_FAIL:
return( CRYPT_ERROR_FAILED );
}
return( defaultError );
}
/* Set up a PIN in the format required by the Fortezza driver */
static void initPIN( CI_PIN pinBuffer, const void *pin, const int pinLength )
{
memset( pinBuffer, 0, sizeof( CI_PIN ) );
if( pinLength )
memcpy( pinBuffer, pin, pinLength );
pinBuffer[ pinLength ] = '\0'; /* Ensure PIN is null-terminated */
}
/* Find a free key register */
static int findFreeKeyRegister( DEVICE_INFO *deviceInfo )
{
int mask = 2, i;
/* Search the register-in-use flags for a free register */
for( i = 1; i < deviceInfo->keyRegisterCount; i++ )
{
if( !( deviceInfo->keyRegisterFlags & mask ) )
break;
mask <<= 1;
}
return( ( i == deviceInfo->keyRegisterCount ) ? \
CRYPT_ERROR_OVERFLOW : i );
}
/* Find a free key/certificate slot */
static int findFreeCertificate( DEVICE_INFO *deviceInfo )
{
CI_PERSON *personalityList = deviceInfo->personalities;
int certIndex;
for( certIndex = 0; certIndex < deviceInfo->personalityCount;
certIndex++ )
if( personalityList[ certIndex ].CertLabel[ 0 ] == '\0' )
return( certIndex );
return( CRYPT_ERROR );
}
/* Find a certificate/personality using the labelling system defined in
SDN.605 */
static int findCertificate( DEVICE_INFO *deviceInfo, const char *label,
const int labelLength )
{
static const char *names[] = {
"DSAI", "DSAO", "DSAX", /* DSA individual, org, cert-only */
"KEAK", "KEAX", /* KEA, cert-only */
"CAX1", "PCA1", "PAA1", /* DSA CA, PCA, PAA */
"INKS", "ONKS", /* Legacy DSA+KEA individual, org */
"INKX", "ONKX", /* Legacy KEA individual, org */
NULL };
CI_PERSON *personalityList = deviceInfo->personalities;
int labelIndex, certIndex;
/* If a label is specified, look for the cert for the personality with
the given label */
if( label != NULL )
{
for( certIndex = 0; certIndex < deviceInfo->personalityCount;
certIndex++ )
if( !memcmp( personalityList[ certIndex ].CertLabel + 8, label,
labelLength ) )
return( certIndex );
return( CRYPT_ERROR );
}
/* No label given, look for the certificate in order of likeliness.
First we look for a personal certificate with a signing key, if that
fails we look for an organisational certificate with a signing key */
for( labelIndex = 0; names[ labelIndex ] != NULL; labelIndex++ )
for( certIndex = 0; certIndex < deviceInfo->personalityCount;
certIndex++ )
if( !strncmp( personalityList[ certIndex ].CertLabel, \
names[ labelIndex ], 4 ) )
return( certIndex );
return( CRYPT_ERROR );
}
/* Build a list of hashes of all certificates on the card */
static void getCertificateInfo( DEVICE_INFO *deviceInfo )
{
CI_PERSON *personalityList = deviceInfo->personalities;
CI_HASHVALUE *hashList = deviceInfo->certHashes;
CI_CERTIFICATE certificate;
HASHFUNCTION hashFunction;
int hashSize, certIndex, certSize;
/* Get the hash algorithm information */
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
memset( hashList, 0, deviceInfo->personalityCount * sizeof( CI_HASHVALUE ) );
for( certIndex = 0; certIndex < deviceInfo->personalityCount; certIndex++ )
{
/* If there's no cert present at this location, continue */
if( !personalityList[ certIndex ].CertLabel[ 0 ] || \
pCI_GetCertificate( certIndex, certificate ) != CI_OK )
continue;
/* Get the hash of the certificate data. Sometimes the card can
contain existing cert entries with garbage values so we don't
hash the cert data if it doesn't look right */
certSize = getObjectLength( certificate, sizeof( CI_CERTIFICATE ) );
if( certificate[ 0 ] != BER_SEQUENCE || \
certSize < 256 || certSize > CI_CERT_SIZE )
continue;
hashFunction( NULL, hashList[ certIndex ], certificate, certSize,
HASH_ALL );
}
deviceInfo->certHashesInitialised = TRUE;
}
/* Update certificate/personality information to reflect changes made in the
device */
static void updateCertificateInfo( DEVICE_INFO *deviceInfo,
const int certIndex,
const void *certificate,
const int certSize, const char *label )
{
CI_PERSON *personality = getPersonality( deviceInfo, certIndex );
CI_HASHVALUE *hashList = deviceInfo->certHashes;
/* Update the hash for the certificate if necessary */
if( deviceInfo->certHashesInitialised )
if( certSize != CRYPT_UNUSED )
{
HASHFUNCTION hashFunction;
int hashSize;
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
hashFunction( NULL, hashList[ certIndex ], ( void * ) certificate,
certSize, HASH_ALL );
}
else
/* There's no cert present at this location, make sure the hash
is zero */
memset( hashList[ certIndex ], 0, sizeof( CI_HASHVALUE ) );
/* Update the label for the certificate/personality */
memset( personality->CertLabel, 0, sizeof( CI_CERT_STR ) );
strcpy( personality->CertLabel, label );
}
/* Set up certificate information and load it into the card */
static int updateCertificate( DEVICE_INFO *deviceInfo, const int certIndex,
const CRYPT_CERTIFICATE iCryptCert,
const void *certData, const int certDataSize,
const char *labelData, const int parentIndex )
{
CI_PERSON *personalityList = deviceInfo->personalities;
CI_CERT_STR label;
CI_CERTIFICATE certificate;
int certificateLength = CRYPT_UNUSED, status;
/* Set up the label for the certificate. This is somewhat ad hoc since
non-DOD Fortezza usage won't follow the somewhat peculiar certification
heirarchy designed for DOD/government use, so we just mark a cert as
CA/individual rather than CA/PCA/PAA. In addition we select between
organisational and individual certs based on whether an
organizationName or organizationalUnitName is present */
memset( label, 0, sizeof( CI_CERT_STR ) );
if( certData == NULL )
{
CI_PERSON *personality = getPersonality( deviceInfo, certIndex );
const BOOLEAN newEntry = personality->CertLabel[ 0 ] ? FALSE : TRUE;
int value;
/* Determine the appropriate label for the cert */
status = krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_CA );
if( cryptStatusOK( status ) && value )
strcpy( label, "CAX1FF" );
else
{
/* If there's a key agreement key usage, it must be KEA */
status = krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_KEYUSAGE );
if( cryptStatusOK( status ) && \
( value & ( CRYPT_KEYUSAGE_KEYAGREEMENT | \
CRYPT_KEYUSAGE_ENCIPHERONLY | \
CRYPT_KEYUSAGE_DECIPHERONLY ) ) )
strcpy( label, "KEAKFF" );
else
{
RESOURCE_DATA msgData;
/* Select the SubjectName as the current DN and check whether
there's organisation-related components present. Given the
dog's breakfast of DN components present in most certs this
will probably misidentify individual keys as organisational
ones some of the time, but it's unlikely that anything
distinguishes between I and O keys anyway */
value = CRYPT_UNUSED;
krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_SETATTRIBUTE,
&value, CRYPT_CERTINFO_SUBJECTNAME );
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptCert,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_ORGANIZATIONNAME );
if( status == CRYPT_ERROR_NOTFOUND )
{
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptCert,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
}
strcpy( label, ( status == CRYPT_ERROR_NOTFOUND ) ? \
"DSAIFF" : "DSAOFF" );
}
/* If it's a completely new entry (ie one which doesn't
correspond to a private key), mark it as a cert-only key */
if( newEntry )
label[ 3 ] = 'X';
}
sprintf( label + 6, "%02X", ( parentIndex != CRYPT_UNUSED ) ?
parentIndex : 0xFF );
/* Special-case override: If this is certificate slot 0, it's a PAA
cert being installed by the SSO */
if( !certIndex )
memcpy( label, "PAA1FFFF", 8 );
/* If there's label data supplied (which happens for cert-only certs
with no associated personality), use that */
if( labelData != NULL )
strcpy( label + 8, labelData );
else
/* Reuse the existing label */
strcpy( label + 8, personality->CertLabel + 8 );
}
else
{
/* Set the SDN.605 related certificate locator to indicate that no
parent or sibling certificates are present for this key, and use
the cryptlib U/E specifier "TEMP" to indicate a temporary key
awaiting a certificate */
strcpy( label, "TEMPFFFF" );
strncpy( label + 8, labelData, 24 );
}
/* Set up the certificate data and send it to the card */
memset( certificate, 0, sizeof( CI_CERTIFICATE ) );
if( certData == NULL )
{
RESOURCE_DATA msgData;
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENC_CERT );
if( cryptStatusOK( status ) )
{
certificateLength = msgData.length;
if( certificateLength > sizeof( CI_CERTIFICATE ) )
return( CRYPT_ERROR_OVERFLOW );
setResourceData( &msgData, certificate, certificateLength );
status = krnlSendMessage( iCryptCert,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ENC_CERT );
}
if( cryptStatusError( status ) )
return( status );
}
else
memcpy( certificate, certData, certDataSize );
#ifndef NO_UPDATE
status = pCI_LoadCertificate( certIndex, label, certificate, 0 );
if( status != CI_OK )
return( mapError( status, CRYPT_ERROR_FAILED ) );
#endif /* NO_UPDATE */
/* Update the in-memory copy of the cert information */
updateCertificateInfo( deviceInfo, certIndex, certificate,
certificateLength, label );
return( CRYPT_OK );
}
/* Update a card using the certs in a cert chain */
static int updateCertChain( DEVICE_INFO *deviceInfo,
const CRYPT_CERTIFICATE iCryptCert,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -