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

📄 pkcs15_rd.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
		for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
			if( ( pkcs15infoPtr[ i ].type == PKCS15_SUBTYPE_DATA && \
				  pkcs15infoPtr[ i ].dataType == dataType ) )
				break;
		if( i == MAX_PKCS15_OBJECTS )
			return( CRYPT_ERROR_NOTFOUND );
		pkcs15infoPtr = &pkcs15infoPtr[ i ];

		/* Return it to the caller */
		length = pkcs15infoPtr->dataDataSize - pkcs15infoPtr->dataOffset;
		if( data != NULL )
			{
			if( *dataLength < length )
				{
				assert( NOTREACHED );
				return( CRYPT_ERROR_OVERFLOW );
				}
			memcpy( data, ( BYTE * ) pkcs15infoPtr->dataData + \
									 pkcs15infoPtr->dataOffset, length );
			}
		*dataLength = length;
		return( CRYPT_OK );
		}

	/* If this is the first cert, reset the index value.  This is pretty
	   ugly since this sort of value should be stored with the caller,
	   however there's no way to pass this back and forth in a RESOURCE_DATA
	   without resorting to an even uglier hack and it's safe since this
	   attribute is only ever read for the config keyset */
	if( dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT )
		trustedCertIndex = 0;

	/* If we're being asked for a trusted cert, find the first or next one */
	while( trustedCertIndex < MAX_PKCS15_OBJECTS )
		{
		if( pkcs15infoPtr[ trustedCertIndex ].implicitTrust )
			{
			const int length =
						pkcs15infoPtr[ trustedCertIndex ].certDataSize - \
						pkcs15infoPtr[ trustedCertIndex ].certOffset;
			int status = CRYPT_OK;

			assert( isWritePtr( data, *dataLength ) );
			if( *dataLength < length )
				{
				assert( NOTREACHED );
				status = CRYPT_ERROR_OVERFLOW;
				}
			else
				memcpy( data,
						( BYTE * ) pkcs15infoPtr[ trustedCertIndex ].certData + \
								   pkcs15infoPtr[ trustedCertIndex ].certOffset,
						length );
			*dataLength = length;
			trustedCertIndex++;	/* Move on to the next cert */
			return( status );
			}
		trustedCertIndex++;
		}

	return( CRYPT_ERROR_NOTFOUND );
	}

/* Read key data from a PKCS #15 collection */

static int getItemFunction( KEYSET_INFO *keysetInfo,
							CRYPT_HANDLE *iCryptHandle,
							const KEYMGMT_ITEM_TYPE itemType,
							const CRYPT_KEYID_TYPE keyIDtype,
							const void *keyID, const int keyIDlength,
							void *auxInfo, int *auxInfoLength,
							const int flags )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	CRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;
	CRYPT_CONTEXT iCryptContext;
	const PKCS15_INFO *pkcs15infoPtr;
	RESOURCE_DATA msgData;
	STREAM stream;
	const BOOLEAN publicComponentsOnly = \
					( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? TRUE : FALSE;
	int pubkeyActionFlags = 0, privkeyActionFlags = 0, status;

	/* If we're being asked for encoded configuration information, return it
	   and exit.  This is a bit odd, but more valid than defining a pile of
	   special-case KEYMGMT_ITEM types that only exist for PKCS #15 keysets,
	   since these are really attributes of the keyset rather than general 
	   key types */
	if( iCryptHandle == NULL )
		{
		assert( keyIDtype == CRYPT_KEYID_NONE );
		assert( keyID == NULL ); assert( keyIDlength == 0 );

		return( getConfigItem( keysetInfo, flags, auxInfo, auxInfoLength ) );
		}

	assert( iCryptHandle != NULL );
	assert( keyIDtype == CRYPT_KEYID_NAME || \
			keyIDtype == CRYPT_KEYID_URI || \
			keyIDtype == CRYPT_IKEYID_KEYID || \
			keyIDtype == CRYPT_IKEYID_PGPKEYID || \
			keyIDtype == CRYPT_IKEYID_ISSUERID );
	assert( keyID != NULL ); assert( keyIDlength >= 1 );

	/* Clear the return values */
	*iCryptHandle = CRYPT_ERROR;

	/* Locate the appropriate object in the PKCS #15 collection and make sure
	   the components we need are present: Either a public key or a cert for
	   any read, and a private key as well for a private-key read */
	pkcs15infoPtr = findEntry( keysetInfo->keyData, keyIDtype,
							   keyID, keyIDlength, flags );
	if( pkcs15infoPtr == NULL || \
		( pkcs15infoPtr->pubKeyData == NULL && \
		  pkcs15infoPtr->certData == NULL ) )
		/* There's not enough information present to get a public key or the
		   public portions of a private key */
		return( CRYPT_ERROR_NOTFOUND );
	if( !publicComponentsOnly && pkcs15infoPtr->privKeyData == NULL )
		/* There's not enough information present to get a private key */
		return( CRYPT_ERROR_NOTFOUND );

	/* If we're just checking whether an object exists, return now.  If all
	   we want is the key label, copy it back to the caller and exit */
	if( flags & KEYMGMT_FLAG_CHECK_ONLY )
		return( CRYPT_OK );
	if( flags & KEYMGMT_FLAG_LABEL_ONLY )
		{
		*auxInfoLength = pkcs15infoPtr->labelLength;
		if( auxInfo != NULL )
			memcpy( auxInfo, pkcs15infoPtr->label,
					pkcs15infoPtr->labelLength );
		return( CRYPT_OK );
		}

	/* If we're reading the private key, make sure that the user has 
	   supplied a password.  This is checked by the kernel, but we perform 
	   another check here just to be safe*/
	if( !publicComponentsOnly && auxInfo == NULL )
		return( CRYPT_ERROR_WRONGKEY );

	/* Read the public components.  If we're creating a public-key context we
	   create the cert or PKC context normally, if we're creating a private-
	   key context we create a data-only cert (if there's cert information 
	   present) and a partial PKC context ready to accept the private key 
	   components.  If there's a cert present we take all the info we need 
	   from the cert, otherwise we use the public-key data */
	if( pkcs15infoPtr->certData != NULL )
		{
		/* There's a certificate present, import it and reconstruct the 
		   public-key info from it if we're creating a partial PKC context */
		status = iCryptImportCertIndirect( &iCryptContext,
								keysetInfo->objectHandle, keyIDtype, keyID,
								keyIDlength, publicComponentsOnly ? \
									KEYMGMT_FLAG_NONE : \
									KEYMGMT_FLAG_DATAONLY_CERT );
		if( cryptStatusOK( status ) && !publicComponentsOnly )
			{
			DYNBUF pubKeyDB;

			iDataCert = iCryptContext;	/* We got the cert, now get the context */
			status = dynCreate( &pubKeyDB, iDataCert, CRYPT_IATTRIBUTE_SPKI );
			if( cryptStatusError( status ) )
				return( status );
			sMemConnect( &stream, dynData( pubKeyDB ), 
						 dynLength( pubKeyDB ) );
			status = iCryptReadSubjectPublicKey( &stream, &iCryptContext, 
												 TRUE );
			sMemDisconnect( &stream );
			dynDestroy( &pubKeyDB );
			}
		}
	else
		{
		/* There's no certificate present, create the public-key context
		   directly */
		sMemConnect( &stream, ( BYTE * ) pkcs15infoPtr->pubKeyData + \
						pkcs15infoPtr->pubKeyOffset, 
					 pkcs15infoPtr->pubKeyDataSize - \
						pkcs15infoPtr->pubKeyOffset );
		status = iCryptReadSubjectPublicKey( &stream, &iCryptContext, 
											 !publicComponentsOnly );
		sMemDisconnect( &stream );
		}
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
								  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );

	/* Get the permitted usage flags for each object type that we'll be
	   instantiating.  If there's a public key present we apply its usage
	   flags to whichever PKC context we create, even if it's done indirectly
	   via the cert import.  Since the private key can also perform the
	   actions of the public key, we set its action flags to the union of the
	   two */
	if( pkcs15infoPtr->pubKeyData != NULL )
		{
		pubkeyActionFlags = getPermittedActions( pkcs15infoPtr->pubKeyUsage,
												 cryptAlgo );
		if( cryptStatusError( pubkeyActionFlags ) )
			status = pubkeyActionFlags;
		}
	if( !publicComponentsOnly )
		{
		privkeyActionFlags = getPermittedActions( pkcs15infoPtr->privKeyUsage,
												  cryptAlgo );
		if( cryptStatusError( privkeyActionFlags ) )
			status = privkeyActionFlags;
		privkeyActionFlags |= pubkeyActionFlags;
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		if( iDataCert != CRYPT_ERROR )
			krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
		}

	/* If we're only interested in the public components, set the key 
	   permissions and exit */
	if( publicComponentsOnly )
		{
		status = setKeyAttributes( iCryptContext, pkcs15infoPtr, 
								   ( pkcs15infoPtr->pubKeyData != NULL ) ? \
								   pubkeyActionFlags : CRYPT_UNUSED );
		if( cryptStatusOK( status ) )
			*iCryptHandle = iCryptContext;
		else
			krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	assert( ( pkcs15infoPtr->pubKeyData != NULL || \
			  pkcs15infoPtr->certData != NULL ) && \
			pkcs15infoPtr->privKeyData != NULL );

	/* Set the key label.  We have to do this before we load the key or the
	   key load will be blocked by the kernel */
	setMessageData( &msgData, ( void * ) pkcs15infoPtr->label,
					pkcs15infoPtr->labelLength );
	krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData, 
					 CRYPT_CTXINFO_LABEL );

	/* Read the private key header fields and import the private key */
	sMemConnect( &stream, 
				 ( BYTE * ) pkcs15infoPtr->privKeyData + \
							pkcs15infoPtr->privKeyOffset,
				 pkcs15infoPtr->privKeyDataSize - \
							pkcs15infoPtr->privKeyOffset );
	status = readConstructed( &stream, NULL, CTAG_OV_DIRECTPROTECTED );
	if( cryptStatusOK( status ) )
		status = readEncryptedKey( &stream, iCryptContext, auxInfo,
								   *auxInfoLength );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		if( iDataCert != CRYPT_ERROR )
			krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Connect the data-only certificate object to the context if it exists.
	   This is an internal object used only by the context so we tell the
	   kernel to mark it as owned by the context only */
	if( iDataCert != CRYPT_ERROR )
		krnlSendMessage( iCryptContext, IMESSAGE_SETDEPENDENT, &iDataCert, 
						 SETDEP_OPTION_NOINCREF );

	/* Set the permitted action flags */
	status = setKeyAttributes( iCryptContext, pkcs15infoPtr, 
							   privkeyActionFlags );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptContext, MESSAGE_DECREFCOUNT );
		return( status );
		}

	*iCryptHandle = iCryptContext;
	return( CRYPT_OK );
	}

/* Fetch a sequence of certs.  These functions are called indirectly by the
   certificate code to fetch the first and subsequent certs in a chain */

static int getItem( PKCS15_INFO *pkcs15info, CRYPT_CERTIFICATE *iCertificate, 
					int *stateInfo, const CRYPT_KEYID_TYPE keyIDtype, 
					const void *keyID, const int keyIDlength, 
					const KEYMGMT_ITEM_TYPE itemType, const int options )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	const PKCS15_INFO *pkcs15infoPtr;
	int status;
	
	/* Find the appropriate entry based on the ID */
	pkcs15infoPtr = findEntry( pkcs15info, keyIDtype, keyID, keyIDlength, 
							   options );
	if( pkcs15infoPtr == NULL )
		{
		*stateInfo = CRYPT_ERROR;
		return( CRYPT_ERROR_NOTFOUND );
		}
	*stateInfo = pkcs15infoPtr->index;

	/* Import the cert */
	setMessageCreateObjectIndirectInfo( &createInfo,
			( BYTE * ) pkcs15infoPtr->certData + pkcs15infoPtr->certOffset,
			pkcs15infoPtr->certDataSize - pkcs15infoPtr->certOffset,
			( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
				CERTFORMAT_DATAONLY : CRYPT_CERTTYPE_CERTIFICATE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT, &createInfo, 
							  OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusOK( status ) )
		{
		*iCertificate = createInfo.cryptHandle;
		if( pkcs15infoPtr->validFrom == 0 )
			/* Perform an opportunistic update of the validity info if
			   this hasn't already been set */
			getValidityInfo( pkcs15info, createInfo.cryptHandle );
		}
	return( status );
	}

static int getFirstItemFunction( KEYSET_INFO *keysetInfo,
								 CRYPT_CERTIFICATE *iCertificate,
								 int *stateInfo,
								 const CRYPT_KEYID_TYPE keyIDtype,
								 const void *keyID, const int keyIDlength,
								 const KEYMGMT_ITEM_TYPE itemType,
								 const int options )
	{
	assert( stateInfo != NULL );
	assert( keyIDtype != CRYPT_KEYID_NONE && keyID != NULL && \
			keyIDlength > 0 );
	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );

	return( getItem( keysetInfo->keyData, iCertificate, stateInfo,
					 keyIDtype, keyID, keyIDlength, itemType, options ) );
	}

static int getNextItemFunction( KEYSET_INFO *keysetInfo,
								CRYPT_CERTIFICATE *iCertificate,
								int *stateInfo, const int options )
	{
	PKCS15_INFO *pkcs15infoPtr = keysetInfo->keyData;

	assert( stateInfo != NULL );
	assert( ( *stateInfo >= 0 && *stateInfo < MAX_PKCS15_OBJECTS ) || \
			*stateInfo == CRYPT_ERROR );

	/* If the previous cert was the last one, there's nothing left to fetch */
	if( *stateInfo == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Find the cert for which the subjectNameID matches this cert's
	   issuerNameID */
	return( getItem( pkcs15infoPtr, iCertificate, stateInfo,
					 CRYPT_KEYIDEX_SUBJECTNAMEID, 
					 pkcs15infoPtr[ *stateInfo ].issuerNameID, 
					 pkcs15infoPtr[ *stateInfo ].issuerNameIDlength, 
					 KEYMGMT_ITEM_PUBLICKEY, options ) );
	}

/****************************************************************************
*																			*
*							Keyset Access Routines							*
*																			*
****************************************************************************/

void initPKCS15read( KEYSET_INFO *keysetInfo )
	{
	keysetInfo->getItemFunction = getItemFunction;
	keysetInfo->getFirstItemFunction = getFirstItemFunction;
	keysetInfo->getNextItemFunction = getNextItemFunction;
	}
#endif /* USE_PKCS15 */

⌨️ 快捷键说明

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