📄 dev_fort.c
字号:
strlen( fortezzaInfo->initPIN ) );
initPIN( newPIN, data, dataLength );
status = pCI_ChangePIN( CI_SSO_PIN, oldPIN, newPIN );
zeroise( fortezzaInfo->initPIN, CRYPT_MAX_TEXTSIZE );
return( ( status == CI_FAIL ) ? CRYPT_ERROR_WRONGKEY : \
mapError( status, CRYPT_ERROR_WRONGKEY ) );
}
if( type == CRYPT_DEVINFO_SET_AUTHENT_USER )
{
CI_PIN oldPIN, newPIN;
/* This assumes that we're in the SSO initialised state and are
setting the initial user PIN to move us into the user initialised
state, for which oldPIN == newPIN */
initPIN( oldPIN, data, dataLength );
initPIN( newPIN, data, dataLength );
status = pCI_ChangePIN( CI_USER_PIN, oldPIN, newPIN );
return( ( status == CI_FAIL ) ? CRYPT_ERROR_WRONGKEY : \
mapError( status, CRYPT_ERROR_WRONGKEY ) );
}
/* Handle initialisation */
if( type == CRYPT_DEVINFO_INITIALISE )
{
CI_RANDOM randomBuffer;
CI_STATE deviceState;
CI_PIN pin;
/* Make sure that the device is in the uninitialised state */
status = pCI_GetState( &deviceState );
if( status != CI_OK || deviceState != CI_UNINITIALIZED )
return( CRYPT_ERROR_INITED );
/* Log on with the SSO PIN */
initPIN( pin, data, dataLength );
status = pCI_CheckPIN( CI_SSO_PIN, pin );
if( status != CI_OK )
return( mapError( status, CRYPT_ERROR_FAILED ) );
/* Load the random number seed and storage key from the device's
RNG output and make sure that the card has now in the
initialised state */
status = pCI_GenerateRandom( randomBuffer );
if( status == CI_OK )
status = pCI_LoadInitValues( randomBuffer,
randomBuffer + sizeof( CI_RANDSEED ) );
zeroise( randomBuffer, sizeof( CI_RANDOM ) );
if( status == CI_OK )
status = pCI_GetState( &deviceState );
if( status != CI_OK )
return( mapError( status, CRYPT_ERROR_FAILED ) );
if( deviceState != CI_INITIALIZED )
return( CRYPT_ERROR_FAILED );
/* Remember the initialisation PIN for a future CI_ChangePIN() */
memcpy( fortezzaInfo->initPIN, data, dataLength );
fortezzaInfo->initPIN[ dataLength ] = '\0';
return( CRYPT_OK );
}
/* Handle zeroisation */
if( type == CRYPT_DEVINFO_ZEROISE )
{
CI_STATE deviceState;
CI_PIN pin;
/* Zeroise the card */
status = pCI_Zeroize();
if( status == CI_OK )
status = pCI_GetState( &deviceState );
if( status != CI_OK )
return( mapError( status, CRYPT_ERROR_FAILED ) );
if( deviceState != CI_ZEROIZED )
return( CRYPT_ERROR_FAILED );
/* Clear any in-memory state information that we were holding about
the card */
memset( fortezzaInfo->personalities, 0,
fortezzaInfo->personalityCount * sizeof( CI_PERSON ) );
memset( fortezzaInfo->certHashes, 0,
fortezzaInfo->personalityCount * sizeof( CI_HASHVALUE ) );
fortezzaInfo->certHashesInitialised = FALSE;
fortezzaInfo->currentPersonality = CRYPT_ERROR;
/* Log on with the zeroise PIN to move it into the uninitialised
state */
initPIN( pin, data, dataLength );
status = pCI_CheckPIN( CI_SSO_PIN, pin );
return( mapError( status, CRYPT_ERROR_WRONGKEY ) );
}
/* Handle high-reliability time */
if( type == CRYPT_IATTRIBUTE_TIME )
{
CI_TIME cardTime;
time_t *timePtr = ( time_t * ) data, theTime;
status = pCI_GetTime( cardTime );
if( status != CI_OK )
return( mapError( status, CRYPT_ERROR_FAILED ) );
if( ( theTime = getTokenTime( cardTime ) ) < MIN_TIME_VALUE )
return( CRYPT_ERROR_NOTAVAIL );
*timePtr = getTime();
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL ); /* Get rid of compiler warning */
}
/****************************************************************************
* *
* Misc.Device Interface Routines *
* *
****************************************************************************/
/* Get random data from the device */
static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
const int length )
{
CI_RANDOM randomBuffer;
BYTE *bufPtr = buffer;
int count, status;
/* Get as many 20-byte blocks as required to fill the request */
for( count = 0; count < length; count += 20 )
{
const int noBytes = min( 20, length - count );
status = pCI_GenerateRandom( randomBuffer );
if( status != CI_OK )
break;
memcpy( bufPtr, randomBuffer, noBytes );
bufPtr += noBytes;
}
zeroise( randomBuffer, 20 );
return( mapError( status, CRYPT_ERROR_FAILED ) );
}
/* Instantiate an object in a device. This works like the create context
function but instantiates a cryptlib object using data already contained
in the device (for example a stored private key or certificate). If the
value being read is a public key and there's a certificate attached, the
instantiated object is a native cryptlib object rather than a device
object with a native certificate object attached because there doesn't
appear to be any good reason to create the public-key object in the device,
and the cryptlib native object will probably be faster anyway */
static int getItemFunction( DEVICE_INFO *deviceInfo,
CRYPT_CONTEXT *iCryptContext,
const KEYMGMT_ITEM_TYPE itemType,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
void *auxInfo, int *auxInfoLength,
const int flags )
{
CRYPT_CERTIFICATE iCryptCert;
CRYPT_ALGO_TYPE cryptAlgo;
static const int keySize = 128;
const CAPABILITY_INFO *capabilityInfoPtr;
FORTEZZA_INFO *fortezzaInfo = deviceInfo->deviceFortezza;
CI_PERSON *personality;
CI_CERTIFICATE certificate;
RESOURCE_DATA msgData;
BOOLEAN certPresent = TRUE;
int certIndex, status;
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_PRIVATEKEY );
assert( keyIDtype == CRYPT_KEYID_NAME );
/* Find the referenced personality on the device and determine the
algorithm type for the key */
certIndex = findCertificateFromLabel( fortezzaInfo, keyID, keyIDlength );
if( certIndex == CRYPT_ERROR )
return( CRYPT_ERROR_NOTFOUND );
if( flags & KEYMGMT_FLAG_CHECK_ONLY )
/* If we're just checking whether an object exists, return now */
return( CRYPT_OK );
personality = getPersonality( fortezzaInfo, certIndex );
if( flags & KEYMGMT_FLAG_LABEL_ONLY )
{
/* All we want is the key label, copy it back to the caller and
exit */
*auxInfoLength = strlen( personality->CertLabel + 8 );
if( auxInfo != NULL )
memcpy( auxInfo, personality->CertLabel + 8, *auxInfoLength );
return( CRYPT_OK );
}
status = pCI_GetCertificate( certIndex, certificate );
if( status != CI_OK )
return( mapError( status, CRYPT_ERROR_READ ) );
if( !memcmp( personality->CertLabel, "TEMP", 4 ) )
{
STREAM stream;
/* It's a work in progress, read the algorithm from the start of the
public key data */
sMemConnect( &stream, certificate, 128 );
status = readSequence( &stream, NULL );
if( !cryptStatusError( status ) )
status = readAlgoID( &stream, &cryptAlgo );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
return( status );
/* Remember that there's no cert available for this key */
certPresent = FALSE;
}
else
/* It's a certificate, determine the algorithm type from the label */
if( !memcmp( personality->CertLabel, "DSA", 3 ) || \
!memcmp( personality->CertLabel, "CAX", 3 ) || \
!memcmp( personality->CertLabel, "PCA", 3 ) || \
!memcmp( personality->CertLabel, "PAA", 3 ) )
cryptAlgo = CRYPT_ALGO_DSA;
else
if( !memcmp( personality->CertLabel, "KEA", 3 ) )
cryptAlgo = CRYPT_ALGO_KEA;
else
return( CRYPT_ERROR_BADDATA );
capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfo,
cryptAlgo );
if( capabilityInfoPtr == NULL )
return( CRYPT_ERROR_NOTAVAIL );
/* If we're after a private key, make sure that it really is a private
key. This check isn't completely effective since the CA labels
don't identify the presence of a private key */
if( personality->CertLabel[ 4 ] == 'X' && \
itemType == KEYMGMT_ITEM_PRIVATEKEY )
return( CRYPT_ERROR_NOTFOUND );
/* Try and create a certificate chain that matches the key. The process
is as follows:
if public key
if cert
create native cert chain (+key) object
else
create device pubkey object, mark as "key loaded"
else
create device privkey object, mark as "key loaded"
if cert
create native data-only cert chain object
attach cert chain object to key
The reason for doing things this way is given in the comment at the
top of this section */
if( certPresent )
{
status = iCryptImportCertIndirect( &iCryptCert,
deviceInfo->objectHandle, keyIDtype, keyID,
keyIDlength, ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
KEYMGMT_FLAG_DATAONLY_CERT : 0 );
if( cryptStatusError( status ) )
return( status );
/* We got the cert, if we're being asked for a public key then we've
created a native object to contain it so we return that */
if( itemType == KEYMGMT_ITEM_PUBLICKEY )
{
/* Set up the keying info in the context based on the data from
the cert if necessary */
if( cryptAlgo == CRYPT_ALGO_KEA )
{
BYTE keyDataBuffer[ 1024 ];
setMessageData( &msgData, keyDataBuffer, 1024 );
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SPKI );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iCryptCert,
IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
return( status );
}
}
*iCryptContext = iCryptCert;
return( CRYPT_OK );
}
}
/* Create a dummy context for the key, remember the device it's
contained in, the index of the device-internal key, and the object's
label, mark it as initialised (i.e. with a key loaded), and if
there's a cert present attach it to the context. The cert is an
internal object used only by the context so we tell the kernel to
mark it as owned by the context only */
status = createContextFromCapability( iCryptContext, deviceInfo->ownerHandle,
capabilityInfoPtr,
CREATEOBJECT_FLAG_DUMMY );
if( cryptStatusError( status ) )
{
if( certPresent )
krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
return( status );
}
krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
&deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, &certIndex,
CRYPT_IATTRIBUTE_DEVICEOBJECT );
setMessageData( &msgData, personality->CertLabel + 8,
strlen( personality->CertLabel + 8 ) );
krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_LABEL );
krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
( void * ) &keySize, CRYPT_IATTRIBUTE_KEYSIZE );
if( certPresent && cryptAlgo == CRYPT_ALGO_KEA )
{
BYTE keyDataBuffer[ 1024 ];
/* Set up the keying info in the context based on the data from the
cert if necessary */
setMessageData( &msgData, keyDataBuffer, 1024 );
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SPKI );
if( cryptStatusOK( status ) )
status = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
if( cryptStatusError( status ) )
{
krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
*iCryptContext = CRYPT_ERROR;
return( status );
}
}
else
/* If we don't set keying the info, we have
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -