⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fortezza.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
		pCI_Reset == NULL || pCI_SetKey == NULL || pCI_SetMode == NULL || 
		pCI_SetPersonality == NULL || pCI_Sign == NULL || 
		pCI_Terminate == NULL || pCI_Unlock == NULL || 
		pCI_UnwrapKey == NULL || pCI_VerifySignature == NULL || 
		pCI_WrapKey == NULL || pCI_Zeroize == NULL )
		{
		/* Free the library reference and reset the handle */
		FreeLibrary( hFortezza );
		hFortezza = NULL_HINSTANCE;
		return( CRYPT_ERROR );
		}

	/* Initialise the Fortezza library */
	if( pCI_Initialize( &noSockets ) != CI_OK )
		{
		/* Free the library reference and reset the handle */
		FreeLibrary( hFortezza );
		hFortezza = NULL_HINSTANCE;
		return( CRYPT_ERROR );
		}

	return( CRYPT_OK );
	}

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:
			return( CRYPT_ERROR_PERMISSION );
		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 > 0 )
		memcpy( pinBuffer, pin, pinLength );
	pinBuffer[ pinLength ] = '\0';	/* Ensure that PIN is null-terminated */	
	}

/* Extract the time from a time string */

static time_t getTokenTime( CI_TIME cardTime )
	{
	STREAM stream;
	BYTE buffer[ 32 + 8 ];
	time_t theTime = MIN_TIME_VALUE + 1;
	int length, status;

	/* Convert the token time to an ASN.1 time string that we can read using
	   the standard ASN.1 routines by writing a dummy time value and inserting 
	   the token's time string in its place */
	sMemOpen( &stream, buffer, 32 );
	writeGeneralizedTime( &stream, theTime, DEFAULT_TAG );
	length = stell( &stream );
	sMemDisconnect( &stream );
	memcpy( buffer + 2, cardTime, 14 );
	sMemConnect( &stream, buffer, length );
	status = readGeneralizedTime( &stream, &theTime );
	sMemDisconnect( &stream );
	
	return( ( cryptStatusOK( status ) ) ? theTime : 0 );
	}

/* Find a free key register */

static int findFreeKeyRegister( const FORTEZZA_INFO *fortezzaInfo )
	{
	int mask = 2, i;

	/* Search the register-in-use flags for a free register */
	for( i = 1; i < fortezzaInfo->keyRegisterCount && \
				i < FAILSAFE_ITERATIONS_MED; i++ )
		{
		if( !( fortezzaInfo->keyRegisterFlags & mask ) )
			break;
		mask <<= 1;
		}
	if( i >= FAILSAFE_ITERATIONS_MED )
		retIntError();
	
	return( ( i >= fortezzaInfo->keyRegisterCount ) ? \
			CRYPT_ERROR_OVERFLOW : i );
	}

/* Find a free key/certificate slot */

static int findFreeCertificate( const FORTEZZA_INFO *fortezzaInfo )
	{
	CI_PERSON *personalityList = fortezzaInfo->personalities;
	int certIndex;

	for( certIndex = 0; certIndex < fortezzaInfo->personalityCount && \
						certIndex < FAILSAFE_ITERATIONS_MED; 
		 certIndex++ )
		{
		if( personalityList[ certIndex ].CertLabel[ 0 ] == '\0' )
			return( certIndex );
		}
	if( certIndex >= FAILSAFE_ITERATIONS_MED )
		retIntError();

	return( CRYPT_ERROR );
	}

/* Set a certificate/personality label using the labelling system defined 
   in SDN.605.  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 certificate as CA/individual rather 
   than CA/PCA/PAA.  In addition we select between organisational and 
   individual certificates based on whether an organizationName or 
   organizationalUnitName is present */

static void getCertificateLabel( const int certIndex, const int parentIndex,
								 const CRYPT_CERTIFICATE iCryptCert, 
								 const BOOLEAN newEntry, char *label,
								 const int labelMaxLen )
	{
	MESSAGE_DATA msgData;
	int value, status;

	memset( label, 0, sizeof( CI_CERT_STR ) );

	/* If this is certificate slot 0, it's a PAA certificate being installed 
	   by the SSO */
	if( certIndex <= 0 )
		{
		memcpy( label, "PAA1FFFF", 8 );

		return;
		}

	/* Check to see whether it's a CA certificate.  If it is, label it as a 
	   generic CA key (which encompasses all of CA/PCA/PAA) */
	status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,
							  &value, CRYPT_CERTINFO_CA );
	if( cryptStatusOK( status ) && value > 0 )
		{
		sprintf_s( label, labelMaxLen, "CAX1FF%02X", 
				   ( parentIndex != CRYPT_UNUSED ) ? parentIndex : 0xFF );
		
		return;
		}

	/* If there's a key agreement key usage, it must be KEA */
	status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,
							  &value, CRYPT_CERTINFO_KEYUSAGE );
	if( cryptStatusOK( status ) && \
		( value & ( CRYPT_KEYUSAGE_KEYAGREEMENT | \
					CRYPT_KEYUSAGE_ENCIPHERONLY | \
					CRYPT_KEYUSAGE_DECIPHERONLY ) ) )
		{
		sprintf_s( label, labelMaxLen, "KEAKFF%02X", 
				   ( parentIndex != CRYPT_UNUSED ) ? parentIndex : 0xFF );

		return;
		}

	/* 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 certificates this will probably mis-
	   identify 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, IMESSAGE_SETATTRIBUTE, &value, 
					 CRYPT_CERTINFO_SUBJECTNAME );
	setMessageData( &msgData, NULL, 0 );
	status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, &msgData, 
							  CRYPT_CERTINFO_ORGANIZATIONNAME );
	if( status == CRYPT_ERROR_NOTFOUND )
		{
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, 
								  CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
		}
	if( cryptStatusError( status ) )
		sprintf_s( label, labelMaxLen, "DSAIFF%02X", 
				   ( parentIndex != CRYPT_UNUSED ) ? parentIndex : 0xFF );
	else
		sprintf_s( label, labelMaxLen, "DSAOFF%02X", 
				   ( parentIndex != CRYPT_UNUSED ) ? parentIndex : 0xFF );

	/* If it's a completely new entry (i.e. one that doesn't correspond to a 
	   private key), mark it as a certificate-only key */
	if( newEntry > 0 )
		label[ 3 ] = 'X';
	}

/* Find a certificate/personality using the labelling system defined in
   SDN.605 */

static int findCertificateFromLabel( const FORTEZZA_INFO *fortezzaInfo, 
									 const char *label, 
									 const int labelLength )
	{
	static const char *names[] = { 
		"DSAI", "DSAO", "DSAX",		/* DSA individual, org, certificate-only */
		"KEAK", "KEAX",				/* KEA, certificate-only */
		"CAX1", "PCA1", "PAA1",		/* DSA CA, PCA, PAA */
		"INKS", "ONKS",				/* Legacy DSA+KEA individual, org */
		"INKX", "ONKX",				/* Legacy KEA individual, org */
		NULL, NULL };
	CI_PERSON *personalityList = fortezzaInfo->personalities;
	int labelIndex, certIndex;

	/* If a label is specified, look for the certificate for the personality 
	   with the given label */
	if( label != NULL )
		{
		for( certIndex = 0; certIndex < fortezzaInfo->personalityCount && \
							certIndex < FAILSAFE_ITERATIONS_MED; \
			 certIndex++ )
			{
			if( !memcmp( personalityList[ certIndex ].CertLabel + 8, label, 
						 labelLength ) )
				return( certIndex );
			}
		if( certIndex >= FAILSAFE_ITERATIONS_MED )
			retIntError();

		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 < FAILSAFE_ARRAYSIZE( names, char * ); 
		 labelIndex++ )
		{
		for( certIndex = 0; certIndex < fortezzaInfo->personalityCount && \
							certIndex < FAILSAFE_ITERATIONS_MED; \
			 certIndex++ )
			{
			if( !strncmp( personalityList[ certIndex ].CertLabel, \
						  names[ labelIndex ], 4 ) )
				return( certIndex );
			}
		if( certIndex >= FAILSAFE_ITERATIONS_MED )
			retIntError();
		}
	if( labelIndex >= FAILSAFE_ARRAYSIZE( names, char * ) )
		retIntError();

	return( CRYPT_ERROR );
	}

/* Build a list of hashes of all certificates on the card */

static void getCertificateInfo( FORTEZZA_INFO *fortezzaInfo )
	{
	CI_PERSON *personalityList = fortezzaInfo->personalities;
	CI_HASHVALUE *hashList = fortezzaInfo->certHashes;
	CI_CERTIFICATE certificate;
	HASHFUNCTION_ATOMIC hashFunctionAtomic;
	int certIndex, certSize;

	getHashAtomicParameters( CRYPT_ALGO_SHA1, &hashFunctionAtomic, NULL );
	memset( hashList, 0, fortezzaInfo->personalityCount * sizeof( CI_HASHVALUE ) );
	for( certIndex = 0; certIndex < fortezzaInfo->personalityCount && \
						certIndex < FAILSAFE_ITERATIONS_MED; certIndex++ )
		{
		STREAM stream;
		int status;

		/* If there's no certificate present at this location, continue */
		if( personalityList[ certIndex ].CertLabel[ 0 ] == '\0' || \
			pCI_GetCertificate( certIndex, certificate ) != CI_OK )
			continue;

		/* Get the hash of the certificate data.  Sometimes the card can
		   contain existing certificate entries with garbage values so we 
		   don't hash the certificate data if it doesn't look right */
		sMemConnect( &stream, certificate, sizeof( CI_CERTIFICATE ) );
		status = readSequence( &stream, &certSize );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) || \
			certSize < 256 || certSize > CI_CERT_SIZE - 4 )
			continue;
		hashFunctionAtomic( hashList[ certIndex ], sizeof( CI_HASHVALUE ),
							certificate, ( int ) sizeofObject( certSize ) );
		}
	if( certIndex >= FAILSAFE_ITERATIONS_MED )
		retIntError_Void();
	fortezzaInfo->certHashesInitialised = TRUE;
	}

/* Find a certificate based on its hash value */

static int findCertFromHash( const FORTEZZA_INFO *fortezzaInfo,
							 const void *certHash )
	{
	CI_HASHVALUE *hashList = fortezzaInfo->certHashes;
	int certIndex;

	for( certIndex = 0; certIndex < fortezzaInfo->personalityCount && \
						certIndex < FAILSAFE_ITERATIONS_MED; \
		 certIndex++ )
		{
		if( !memcmp( hashList[ certIndex ], certHash, 
			sizeof( CI_HASHVALUE ) ) )
			return( certIndex );
		}
	if( certIndex >= FAILSAFE_ITERATIONS_MED )
		retIntError();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -