📄 fortezza.c
字号:
return( CRYPT_ERROR_NOTFOUND );
}
/* Update certificate/personality information to reflect changes made in the
device */
static void updateCertificateInfo( FORTEZZA_INFO *fortezzaInfo,
const int certIndex,
const void *certificate,
const int certSize, const char *label )
{
CI_PERSON *personality = getPersonality( fortezzaInfo, certIndex );
CI_HASHVALUE *hashList = fortezzaInfo->certHashes;
/* Update the hash for the certificate/raw key */
if( certificate != NULL )
{
HASHFUNCTION_ATOMIC hashFunctionAtomic;
getHashAtomicParameters( CRYPT_ALGO_SHA1, &hashFunctionAtomic, NULL );
hashFunctionAtomic( hashList[ certIndex ], sizeof( CI_HASHVALUE ),
certificate, certSize );
}
else
{
/* There's no certificate present at this location (for example
because we've just deleted it), make sure that 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 ) );
strlcpy_s( personality->CertLabel, CI_CERT_NAME_SIZE, label );
}
/* 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 labelMaxSize,
const int parentIndex )
{
CI_PERSON *personality = getPersonality( fortezzaInfo, certIndex );
CI_CERTIFICATE certificate;
CI_CERT_STR label;
MESSAGE_DATA msgData;
int certificateLength, status;
/* If we're trying to load the PAA certificate, the device must be in
the SSO initialised state */
if( certIndex <= 0 )
{
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 certificate */
getCertificateLabel( certIndex, parentIndex, iCryptCert,
personality->CertLabel[ 0 ] ? FALSE : TRUE,
label, sizeof( CI_CERT_STR ) );
/* If there's label data supplied (which happens for data-only
certificates with no associated personality), use that */
if( labelData != NULL )
strlcpy_s( label + 8, labelMaxSize - 8, labelData );
else
{
/* Reuse the existing label from the personality corresponding to
the certificate */
strlcpy_s( label + 8, labelMaxSize - 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( cryptStatusError( status ) )
return( 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 certificate 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 */
strlcpy_s( label, CI_NAME_SIZE, "TEMPFFFF" );
strlcat_s( label, CI_NAME_SIZE, labelData );
/* 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 certificate information */
updateCertificateInfo( fortezzaInfo, certIndex, rawKeyData,
rawKeySize, label );
return( CRYPT_OK );
}
/* Information about certificates on the card. The slot index and parent
slot index contain the mapping of certificate positions in the chain to
certificate positions and parent certificate positions in the card, the
certPresent and personalityPresent flags indicate whether the certificate
is already present in the card and whether the certificate being added
corresponds to a personality in the card rather than being a data-only
certificate (e.g. from a CA that issued the end-entity certificate
corresponding to a present personality) */
typedef struct {
int index, parentIndex; /* Pos.of certificate and parent certificate */
BOOLEAN certPresent; /* Whether certificate present in card */
BOOLEAN personalityPresent; /* Whether certificate corresponds to card pers.*/
} CARDCERT_INFO;
/* Update a card using the certificates in a certificate chain */
static int updateCertChain( FORTEZZA_INFO *fortezzaInfo,
const CRYPT_CERTIFICATE iCryptCert )
{
CI_PERSON *personalityList = fortezzaInfo->personalities;
CARDCERT_INFO cardCertInfo[ 16 + 8 ];
int chainIndex = -1, oldCertIndex = -1, value, i, iterationCount = 0;
/* Initialise the certificate index information and hashes for the
certificates on the card if necessary. certList[] contains the
mapping of certificates in the chain to positions in the card,
parentList[] contains the mapping of certificates 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 certificate and work our way down, which
ensures that the CA certificates appear first, and that if an update
fails, the parent certificate pointers point to valid fields (since
higher-level certificates are added first) */
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORLAST, CRYPT_CERTINFO_CURRENT_CERTIFICATE );
/* Pass 1: Build an index of certificate and parent certificate
positions in the card. Once this loop has completed, certList[]
contains a mapping from certificate chain position to position in the
card, and parentList[] contains a mapping from certificate chain
position to parent certificate position in the card */
do
{
MESSAGE_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 certificate 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 certificate to parent certificate position
in the card. The certificate at position 0 is the root
certificate */
if( chainIndex > 0 )
cardCertInfo[ chainIndex ].parentIndex = oldCertIndex;
/* Set the mapping from certificate to position in the card */
if( isPresent )
{
cardCertInfo[ chainIndex ].index = certIndex;
cardCertInfo[ chainIndex ].certPresent = TRUE;
}
else
{
int freeCertIndex;;
/* Allocate this certificate to the next free position in the
card */
for( freeCertIndex = 0;
freeCertIndex < fortezzaInfo->personalityCount && \
personalityList[ freeCertIndex ].CertLabel[ 0 ] != '\0' && \
freeCertIndex < FAILSAFE_ITERATIONS_MED;
freeCertIndex++ );
if( freeCertIndex >= FAILSAFE_ITERATIONS_MED )
retIntError();
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 && \
iterationCount++ < FAILSAFE_ITERATIONS_MED );
if( iterationCount >= FAILSAFE_ITERATIONS_MED )
retIntError();
/* The last certificate 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 certificate, so we find the
location of the corresponding raw and set its index to the raw key
position */
if( !cardCertInfo[ chainIndex ].certPresent )
{
HASHFUNCTION_ATOMIC hashFunctionAtomic;
MESSAGE_DATA msgData;
BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ], keyDataBuffer[ 1024 + 8 ];
int certIndex;
/* Get the keyID for the leaf certificate */
getHashAtomicParameters( CRYPT_ALGO_SHA1, &hashFunctionAtomic, NULL );
setMessageData( &msgData, keyDataBuffer, 1024 );
if( cryptStatusError( \
krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SPKI ) ) )
return( CRYPT_ARGERROR_NUM1 );
hashFunctionAtomic( hash, CRYPT_MAX_HASHSIZE, keyDataBuffer,
msgData.length );
/* If we're not adding the certificate as a data-only PAA
certificate in the 0-th slot (which is a special case with no
corresponding personality present), find the slot for the
certificate 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 certificate */
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 certificate+label as required */
value = CRYPT_CURSOR_LAST;
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
value = CRYPT_CURSOR_PREVIOUS;
chainIndex = 0;
iterationCount = 0;
do
{
CARDCERT_INFO *currentCertInfo = &cardCertInfo[ chainIndex++ ];
char name[ CRYPT_MAX_TEXTSIZE + 1 + 8 ], *labelPtr = NULL;
int status;
/* If the certificate 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[ 16 + 8 ];
int index;
/* If the certificate is present and the parent certificate
index is correct, continue */
if( ( sscanf_s( personalityList[ certIndex ].CertLabel + 6,
"%02X", &index ) == 1 ) && \
( currentCertInfo->parentIndex == index || \
currentCertInfo->parentIndex == CRYPT_UNUSED ) )
continue;
/* Update the parent certificate index in the label, read the
certificate, and write it back out with the new label */
sprintf_s( buffer, 8, "%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 certificate for a non-present personality
(that is, a data-only CA certificate from higher up in the chain
that doesn't correspond to a personality on the card), get holder
identity information from the certificate to use as the label and
make sure that it's within the maximum allowed length */
if( !currentCertInfo->personalityPresent )
{
MESSAGE_DATA msgData;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -