📄 fortezza.c
字号:
}
/* Set up certificate/raw key information and load it into the card */
static int updateCertificate( FORTEZZA_INFO *fortezzaInfo, const int certIndex,
const CRYPT_CERTIFICATE iCryptCert,
const char *labelData, const int parentIndex )
{
CI_PERSON *personality = getPersonality( fortezzaInfo, certIndex );
CI_CERTIFICATE certificate;
CI_CERT_STR label;
RESOURCE_DATA msgData;
int certificateLength, status;
/* If we're trying to load the PAA cert, the device must be in the SSO
initialised state */
if( !certIndex )
{
CI_STATE deviceState;
status = pCI_GetState( &deviceState );
if( status != CI_OK || deviceState != CI_SSO_INITIALIZED )
return( CRYPT_ERROR_PERMISSION );
}
/* Get the SDN.605 label for the cert */
getCertificateLabel( certIndex, parentIndex, iCryptCert,
personality->CertLabel[ 0 ] ? FALSE : TRUE, label );
/* If there's label data supplied (which happens for data-only certs
with no associated personality), use that */
if( labelData != NULL )
strcpy( label + 8, labelData );
else
/* Reuse the existing label from the personality corresponding to
the cert */
strcpy( label + 8, personality->CertLabel + 8 );
/* Set up the certificate data and send it to the card */
memset( certificate, 0, sizeof( CI_CERTIFICATE ) );
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptCert, IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_CERTFORMAT_CERTIFICATE );
if( cryptStatusOK( status ) )
{
certificateLength = msgData.length;
if( certificateLength > sizeof( CI_CERTIFICATE ) )
return( CRYPT_ERROR_OVERFLOW );
setMessageData( &msgData, certificate, certificateLength );
status = krnlSendMessage( iCryptCert, IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_CERTFORMAT_CERTIFICATE );
}
if( cryptStatusError( status ) )
return( status );
#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( fortezzaInfo, certIndex, certificate,
certificateLength, label );
return( CRYPT_OK );
}
static int updateRawKey( FORTEZZA_INFO *fortezzaInfo, const int certIndex,
const void *rawKeyData, const int rawKeySize,
const char *labelData )
{
CI_CERT_STR label;
CI_CERTIFICATE certificate;
int status;
/* 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 raw key data and send it to the card */
memset( certificate, 0, sizeof( CI_CERTIFICATE ) );
memcpy( certificate, rawKeyData, rawKeySize );
#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( fortezzaInfo, certIndex, rawKeyData,
rawKeySize, label );
return( CRYPT_OK );
}
/* Information about certs on the card. The slot index and parent slot
index contain the mapping of cert positions in the chain to cert
positions and parent cert positions in the card, the certPresent and
personalityPresent flags indicate whether the cert is already present in
the card and whether the cert being added corresponds to a personality
in the card rather than being a data-only cert (e.g. from a CA that
issued the end-entity cert corresponding to a present personality) */
typedef struct {
int index, parentIndex; /* Pos.of cert and parent cert */
BOOLEAN certPresent; /* Whether cert present in card */
BOOLEAN personalityPresent; /* Whether cert corresponds to card pers.*/
} CARDCERT_INFO;
/* Update a card using the certs in a cert chain */
static int updateCertChain( FORTEZZA_INFO *fortezzaInfo,
const CRYPT_CERTIFICATE iCryptCert )
{
CI_PERSON *personalityList = fortezzaInfo->personalities;
CARDCERT_INFO cardCertInfo[ 16 ];
int chainIndex = -1, oldCertIndex, value, i;
/* Initialise the certificate index information and hashes for the certs
on the card if necessary. certList[] contains the mapping of certs in
the chain to positions in the card, parentList[] contains the mapping
of certs in the chain to the position of their parents in the card */
for( i = 0; i < 16; i++ )
{
memset( &cardCertInfo[ i ], 0, sizeof( CARDCERT_INFO ) );
cardCertInfo[ i ].index = \
cardCertInfo[ i ].parentIndex = CRYPT_UNUSED;
}
if( !fortezzaInfo->certHashesInitialised )
getCertificateInfo( fortezzaInfo );
/* Start at the top-level cert and work our way down, which ensures that
the CA certs appear first, and that if an update fails, the parent
cert pointers point to valid fields (since higher-level certs are
added first) */
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORLAST, CRYPT_CERTINFO_CURRENT_CERTIFICATE );
/* Pass 1: Build an index of cert and parent cert positions in the card.
Once this loop has completed, certList[] contains a mapping from cert
chain position to position in the card, and parentList[] contains a
mapping from cert chain position to parent cert position in the card */
do
{
RESOURCE_DATA msgData;
CI_HASHVALUE hash;
BOOLEAN isPresent = FALSE;
int certIndex;
/* Increment the chain index. We do this at the start of the loop
since we start at the -1th position */
chainIndex++;
/* Get the hash for this cert and check whether it's already present */
setMessageData( &msgData, &hash, sizeof( CI_HASHVALUE ) );
if( cryptStatusError( \
krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_FINGERPRINT_SHA ) ) )
return( CRYPT_ARGERROR_NUM1 );
certIndex = findCertFromHash( fortezzaInfo, hash );
if( !cryptStatusError( certIndex ) )
isPresent = TRUE;
/* Set the mapping from cert to parent cert position in the card.
The cert at position 0 is the root cert */
if( chainIndex > 0 )
cardCertInfo[ chainIndex ].parentIndex = oldCertIndex;
/* Set the mapping from cert to position in the card */
if( isPresent )
{
cardCertInfo[ chainIndex ].index = certIndex;
cardCertInfo[ chainIndex ].certPresent = TRUE;
}
else
{
int freeCertIndex;;
/* Allocate this cert to the next free position in the card */
for( freeCertIndex = 0; \
freeCertIndex < fortezzaInfo->personalityCount && \
personalityList[ freeCertIndex ].CertLabel[ 0 ] != '\0'; \
freeCertIndex++ );
if( freeCertIndex >= fortezzaInfo->personalityCount )
/* There's no more room for any new certificates in the
card */
return( CRYPT_ERROR_OVERFLOW );
cardCertInfo[ chainIndex ].index = freeCertIndex;
}
/* Remember the just-assigned position in the card */
oldCertIndex = cardCertInfo[ chainIndex ].index;
}
while( krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORPREVIOUS,
CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );
/* The last cert in the chain will either already be present or will be
present in raw-key form. If it's present in raw-key form the previous
code will add it as a pseudo-new cert, so we find the location of the
corresponding raw and set its index to the raw key position */
if( !cardCertInfo[ chainIndex ].certPresent )
{
HASHFUNCTION hashFunction;
RESOURCE_DATA msgData;
BYTE hash[ CRYPT_MAX_HASHSIZE ], keyDataBuffer[ 1024 ];
int certIndex;
/* Get the keyID for the leaf certificate */
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, NULL );
setMessageData( &msgData, keyDataBuffer, 1024 );
if( cryptStatusError( \
krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SPKI ) ) )
return( CRYPT_ARGERROR_NUM1 );
hashFunction( NULL, hash, keyDataBuffer, msgData.length, HASH_ALL );
/* If we're not adding the cert as a data-only PAA cert in the 0-th
slot (which is a special case with no corresponding personality
present), find the slot for the cert based on the location of the
corresponding raw key. If there's no raw key present, we can't
add the chain, since it doesn't correspond to any known key or
cert */
if( cardCertInfo[ chainIndex ].index > 0 )
{
certIndex = findCertFromHash( fortezzaInfo, hash );
if( cryptStatusError( certIndex ) )
return( CRYPT_ERROR_NOTFOUND );
cardCertInfo[ chainIndex ].index = certIndex;
}
cardCertInfo[ chainIndex ].personalityPresent = TRUE;
}
/* Pass 2: Update either the label or cert+label as required */
value = CRYPT_CURSOR_LAST;
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
value = CRYPT_CURSOR_PREVIOUS;
chainIndex = 0;
do
{
CARDCERT_INFO *currentCertInfo = &cardCertInfo[ chainIndex++ ];
char name[ CRYPT_MAX_TEXTSIZE + 1 ], *labelPtr = NULL;
int status;
/* If the cert is already present, make sure that the parent index
info is correct */
if( currentCertInfo->certPresent )
{
CI_CERTIFICATE certificate;
const int certIndex = currentCertInfo->index;
char buffer[ 8 ];
int index;
/* If the cert is present and the parent cert index is correct,
continue */
if( ( sscanf( personalityList[ certIndex ].CertLabel + 6,
"%02X", &index ) == 1 ) && \
( currentCertInfo->parentIndex == index || \
currentCertInfo->parentIndex == CRYPT_UNUSED ) )
continue;
/* Update the parent cert index in the label, read the cert, and
write it back out with the new label */
sprintf( buffer, "%02X", currentCertInfo->parentIndex );
memcpy( personalityList[ certIndex ].CertLabel + 6, buffer, 2 );
status = pCI_GetCertificate( certIndex, certificate );
#ifndef NO_UPDATE
if( status == CI_OK )
status = pCI_LoadCertificate( certIndex,
personalityList[ certIndex ].CertLabel,
certificate, 0 );
#endif /* NO_UPDATE */
if( status != CI_OK )
return( mapError( status, CRYPT_ERROR_WRITE ) );
continue;
}
/* If we're adding a new cert for a non-present personality (that is,
a data-only CA cert from higher up in the chain that doesn't
correspond to a personality on the card), get SubjectName
information from the cert to use as the label and make sure that
it's within the maximum allowed length. Some certs don't have CN
components, so we try for the OU instead. If that also fails, we
try for the O, and if that fails we just use a dummy label
identifying it as a generic CA cert */
if( !currentCertInfo->personalityPresent )
{
RESOURCE_DATA msgData;
value = CRYPT_UNUSED;
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_SUBJECTNAME );
setMessageData( &msgData, name, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_COMMONNAME );
if( status == CRYPT_ERROR_NOTFOUND )
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
if( status == CRYPT_ERROR_NOTFOUND )
status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
if( status == CRYPT_ERROR_NOTFOUND )
strcpy( name, "CA certificate-only entry" );
else
name[ min( msgData.length, 24 ) ] = '\0';
labelPtr = name;
}
/* Write the new cert and label */
status = updateCertificate( fortezzaInfo, currentCertInfo->index,
iCryptCert, labelPtr,
currentCertInfo->parentIndex );
if( cryptStatusError( status ) )
return( status );
}
while( krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Device Init/Shutdown/Device Control Routines *
* *
****************************************************************************/
/* Table of mechanisms supported by this device. These are sorted in order
of frequency of use in order to make lookups a bit faster */
static int exportKEA( DEVICE_INFO *deviceInfo, MECHANISM_WRAP_INFO *mechanismInfo );
static int importKEA( DEVICE_INFO *deviceInfo, MECHANISM_WRAP_INFO *mechanismInfo );
static const MECHANISM_FUNCTION_INFO objectMechanisms[] = {
{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_KEA, exportKEA },
{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_KEA, importKEA },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -