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

📄 dev_fort.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -