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

📄 dev_fort.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
							const int leafCertIndex )
	{
	CI_PERSON *personalityList = deviceInfo->personalities;
	BOOLEAN presentList[ 16 ];
	int certList[ 16 ], parentList[ 16 ];
	int chainIndex = 0, freeCertIndex = 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++ )
		{
		presentList[ i ] = FALSE;
		certList[ i ] = parentList[ i ] = CRYPT_UNUSED;
		}
	if( !deviceInfo->certHashesInitialised )
		getCertificateInfo( deviceInfo );

	/* 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, RESOURCE_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
		{
		CI_HASHVALUE *hashList = deviceInfo->certHashes;
		RESOURCE_DATA msgData;
		CI_HASHVALUE hash;
		BOOLEAN isPresent = FALSE;
		int certIndex;

		/* Get the hash for this cert and check whether it's already present */
		setResourceData( &msgData, &hash, sizeof( CI_HASHVALUE ) );
		if( cryptStatusError( \
			krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							 &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA ) ) )
			return( CRYPT_ARGERROR_NUM1 );
		for( certIndex = 0; certIndex < deviceInfo->personalityCount; certIndex++ )
			if( !memcmp( hashList[ certIndex ], hash, sizeof( CI_HASHVALUE ) ) )
				{
				isPresent = TRUE;
				break;
				}

		/* Set the mapping from cert to parent cert position in the card.  
		   The cert at position 0 is the root cert */
		if( chainIndex != 0 )
			parentList[ chainIndex ] = oldCertIndex;
		
		/* Set the mapping from cert to position in the card */
		if( isPresent )
			{
			certList[ chainIndex ] = certIndex;
			presentList[ chainIndex ] = TRUE;
			}
		else
			{
			/* Make sure there's room for more certificates in the card */
			if( freeCertIndex >= deviceInfo->personalityCount )
				return( CRYPT_ERROR_OVERFLOW );	/* No more room in card */

			/* Allocate this cert to the next free position in the card */
			while( freeCertIndex < deviceInfo->personalityCount && \
				   personalityList[ freeCertIndex ].CertLabel[ 0 ] != '\0' )
				freeCertIndex++;
			certList[ chainIndex ] = freeCertIndex;
			}

		/* Remember the just-assigned position in the card and move on to the
		   next cert in the chain */
		oldCertIndex = certList[ chainIndex ];
		chainIndex++;
		}
	while( krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_SETATTRIBUTE, 
							MESSAGE_VALUE_CURSORPREVIOUS,
							CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );

	/* The last cert in the chain will either already be present, or 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 go back and set its index
	   to the actual position without marking it as present */
	if( certList[ chainIndex - 1 ] == freeCertIndex )
		certList[ chainIndex - 1 ] = leafCertIndex;

	/* Pass 2: Update either the label or cert+label as required */
	value = CRYPT_CURSOR_LAST;
	krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_SETATTRIBUTE, &value, 
					 CRYPT_CERTINFO_CURRENT_CERTIFICATE );
	value = CRYPT_CURSOR_PREVIOUS;
	chainIndex = 0;
	do
		{
		const int parentIndex = parentList[ chainIndex ];
		const int certIndex = certList[ chainIndex ];
		const BOOLEAN isPresent = presentList[ chainIndex++ ];
		char name[ CRYPT_MAX_TEXTSIZE + 1 ], *labelPtr = NULL;
		int status;

		/* If the cert is already present, make sure the parent index info
		   is correct */
		if( isPresent )
			{
			CI_CERTIFICATE certificate;
			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 ) && \
				( parentIndex == index || 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", 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, get 
		   SubjectName information from the cert to use as the label and make 
		   sure 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 */
		if( certIndex != leafCertIndex || !certIndex )
			{
			RESOURCE_DATA msgData;

			value = CRYPT_UNUSED;
			krnlSendMessage( iCryptCert, RESOURCE_IMESSAGE_SETATTRIBUTE, 
							 &value, CRYPT_CERTINFO_SUBJECTNAME );
			setResourceData( &msgData, name, CRYPT_MAX_TEXTSIZE );
			status = krnlSendMessage( iCryptCert, 
								RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								&msgData, CRYPT_CERTINFO_COMMONNAME );
			if( status == CRYPT_ERROR_NOTFOUND )
				status = krnlSendMessage( iCryptCert, 
								RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
			if( status == CRYPT_ERROR_NOTFOUND )
				status = krnlSendMessage( iCryptCert, 
								RESOURCE_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( deviceInfo, certIndex, iCryptCert, 
									NULL, 0, labelPtr, parentIndex );
		if( cryptStatusError( status ) )
			return( status );
		}
	while( krnlSendMessage( iCryptCert, RESOURCE_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 */

int exportKEA( DEVICE_INFO *deviceInfo, MECHANISM_WRAP_INFO *mechanismInfo );
int importKEA( DEVICE_INFO *deviceInfo, MECHANISM_WRAP_INFO *mechanismInfo );

static const MECHANISM_FUNCTION_INFO objectMechanisms[] = {
	{ RESOURCE_MESSAGE_DEV_EXPORT, MECHANISM_KEA, exportKEA },
	{ RESOURCE_MESSAGE_DEV_IMPORT, MECHANISM_KEA, importKEA },
	{ RESOURCE_MESSAGE_NONE, MECHANISM_NONE, NULL }
	};

/* Close a previously-opened session with the device.  We have to have this
   before the init function since it may be called by it if the init process
   fails */

static void shutdownFunction( DEVICE_INFO *deviceInfo )
	{
	/* Clear the personality list if it exists */
	if( deviceInfo->personalities != NULL )
		{
		zeroise( deviceInfo->personalities, 
				 deviceInfo->personalityCount * sizeof( CI_PERSON ) );
		free( deviceInfo->personalities );
		deviceInfo->personalities = NULL;
		deviceInfo->personalityCount = 0;
		}
	if( deviceInfo->certHashes != NULL )
		{
		zeroise( deviceInfo->certHashes, 
				 deviceInfo->personalityCount * sizeof( CI_HASHVALUE ) );
		free( deviceInfo->certHashes );
		deviceInfo->certHashes = NULL;
		deviceInfo->certHashesInitialised = FALSE;
		}

	/* Unlock the socket and close the session with the device */
	if( deviceInfo->flags & DEVICE_LOGGEDIN )
		{
		pCI_Unlock();
		deviceInfo->flags &= ~DEVICE_LOGGEDIN;
		}
	pCI_Close( CI_NULL_FLAG, deviceInfo->slotHandle );
	}

/* Open a session with the device */

static int initFunction( DEVICE_INFO *deviceInfo, const char *name,
						 const int nameLength )
	{
	CI_CONFIG deviceConfiguration;
	int socket, i, status;

	UNUSED( name );

	/* The Fortezza open is in theory a bit problematic since the open will 
	   succeed even if there's no device in the socket, so after we perform 
	   the open we reset the card and check its state to make sure we're not 
	   just rhapsodising into the void.  In practice the currently available
	   (1996-vintage non PnP) NT Fortezza driver won't load unless there's a
	   card inserted so this isn't usually a problem, but multi-slot readers
	   with the card inserted in a slot other than the first one, possible 
	   future drivers, and the Unix driver (which has a dedicated daemon to 
	   handle the card) may not exhibit this behaviour so we check for things
	   working in the manner specified in the docs.

	   The choice of socket for the card can be a bit confusing.  According 
	   to some docs the socket can start from 0 (in violation of the spec),
	   whereas others say they should start from 1, since it doesn't hurt to
	   start from 0 we go from there (typically we just get a 
	   CI_INV_SOCKET_INDEX for slot 0).  Once we've done that, we reset the 
	   card to get it into a known state (although judging by the equivalent
	   time delay of CI_Open() and CI_Reset(), the open does this anyway) and
	   check that a card is actually present (see the comments above - the 
	   NSA must be using their own drivers recovered from crashed UFO's if 
	   their ones really do behave as documented) */
	for( socket = 0; socket <= noSockets; socket++ )
		{
		CI_STATE deviceState;

		/* Try and open the card in the current socket */
		status = pCI_Open( CI_NULL_FLAG, socket );
		if( status != CI_OK )
			continue;
		deviceInfo->slotHandle = socket;

		/* We've opened the card, reset it to get it into a known state
		   and make sure the state is valid.  Unfortunately the exact 
		   definition of a valid state is a bit tricky, for example we 
		   shouldn't allow the initialised or SSO initialised states here 
		   since there doesn't appear to be any way to get from them to 
		   CAW initialised at this point (that is, you need to go 
		   uninitialised -> initialised -> SSO initialised -> CAW 
		   initialised in a straight sequence), however we need to get
		   past this point in order to perform the only valid operation on
		   the card (zeroise) so we have to let these pass even though
		   there's not much we can do in them */
		status = pCI_Reset();
		if( status == CI_OK )
			status = pCI_GetState( &deviceState );
		if( status != CI_OK || \
			( deviceState == CI_POWER_UP || \
			  deviceState == CI_INTERNAL_FAILURE ) )
			{
			pCI_Close( CI_NULL_FLAG, socket );
			if( status == CI_OK )
				status = CI_INV_STATE;
			continue;
			}
		deviceInfo->flags = DEVICE_ACTIVE | DEVICE_NEEDSLOGIN;
		break;
		}
	if( status != CI_OK )
		{
		deviceInfo->errorCode = status;
		return( CRYPT_ERROR_OPEN );
		}

	/* Set up device-specific information.  We can't read the personality 
	   list until the user logs on, so all we can do at this point is 
	   allocate memory for it.  Note that personality 0 can never be selected
	   and so it isn't returned when the personality info is read, this leads 
	   to confusing fencepost errors so when we allocate/read the personality
	   info we leave space for a zero-th personality which is never used */
	pCI_GetConfiguration( &deviceConfiguration );
	deviceInfo->largestBlockSize = deviceConfiguration.LargestBlockSize;
	deviceInfo->minPinSize = 4;
	deviceInfo->maxPinSize = CI_PIN_SIZE;
	deviceInfo->keyRegisterCount = deviceConfiguration.KeyRegisterCount;
	deviceInfo->keyRegisterFlags = 1;	/* Register 0 is reserved */
	deviceInfo->personalityCount = deviceConfiguration.CertificateCount + 1;
	deviceInfo->personalities = malloc( deviceInfo->personalityCount * \
										sizeof( CI_PERSON ) );
	deviceInfo->certHashes = malloc( deviceInfo->personalityCount * \
									 sizeof( CI_HASHVALUE ) );
	deviceInfo->certHashesInitialised = FALSE;
	deviceInfo->currentPersonality = CRYPT_ERROR;
	if( deviceInfo->personalities == NULL || deviceInfo->certHashes == NULL )
		{
		shutdownFunction( deviceInfo );
		return( CRYPT_ERROR_MEMORY );
		}
	memset( deviceInfo->personalities, 0, 
			deviceInfo->personalityCount * sizeof( CI_PERSON ) );
	memset( deviceInfo->certHashes, 0, 
			deviceInfo->personalityCount * sizeof( CI_HASHVALUE ) );
	memcpy( deviceInfo->label, deviceConfiguration.ProductName, 
			CI_NAME_SIZE );
	for( i = CI_NAME_SIZE;
		 i && ( deviceInfo->label[ i - 1 ] == ' ' || \
				!deviceInfo->label[ i - 1 ] ); i-- );
	deviceInfo->label[ i ] = '\0';

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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