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

📄 pkcs11_rw.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						 		Find-Item Routines							*
*																			*
****************************************************************************/

/* Find an object based on a given template.  There are two variations of 
   this, one that finds one and only one object, and the other that returns 
   the first object it finds without treating the presence of multiple 
   objects as an error.
   
   The way in which this call works has special significance, there are PKCS
   #11 implementations that don't allow any other calls during the init/find/
   final sequence, so the code is structured to always call them one after 
   the other without any intervening calls.  In addition some drivers are
   confused over whether they're 1.x or 2.x and may or may not implement
   C_FindObjectsFinal().  Because of this we call it if it exists, if it 
   doesn't we assume that the driver can handle cleanup itself (this 
   situation shouldn't occur because we've checked for 1.x drivers earlier, 
   but there are one or two drivers where it does happen) */

static int findDeviceObjects( PKCS11_INFO *pkcs11Info, 
							  CK_OBJECT_HANDLE *hObject,
							  const CK_ATTRIBUTE *objectTemplate,
							  const CK_ULONG templateCount,
							  const BOOLEAN onlyOne )
	{
	CK_OBJECT_HANDLE hObjectArray[ 2 + 8 ];
	CK_ULONG ulObjectCount;
	CK_RV status;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE  ) ) );
	assert( isReadPtr( objectTemplate, \
					   sizeof( CK_ATTRIBUTE ) * templateCount ) );
	assert( templateCount > 0 );

	status = C_FindObjectsInit( pkcs11Info->hSession,
								( CK_ATTRIBUTE_PTR ) objectTemplate,
								templateCount );
	if( status != CKR_OK )
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_NOTFOUND ) );
	status = C_FindObjects( pkcs11Info->hSession, hObjectArray, 2, 
							&ulObjectCount );
	if( C_FindObjectsFinal != NULL )
		C_FindObjectsFinal( pkcs11Info->hSession );
	if( status != CKR_OK )
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_NOTFOUND ) );
	if( ulObjectCount <= 0 )
		return( CRYPT_ERROR_NOTFOUND );
	if( ulObjectCount > 1 && onlyOne )
		return( CRYPT_ERROR_DUPLICATE );
	if( hObject != NULL )
		{
		assert( hObjectArray[ 0 ] != CK_OBJECT_NONE );

		*hObject = hObjectArray[ 0 ];
		}

	return( CRYPT_OK );
	}

static int findObject( PKCS11_INFO *pkcs11Info, CK_OBJECT_HANDLE *hObject,
					   const CK_ATTRIBUTE *objectTemplate,
					   const CK_ULONG templateCount )
	{
	return( findDeviceObjects( pkcs11Info, hObject, 
							   objectTemplate, templateCount, TRUE ) );
	}

static int findObjectEx( PKCS11_INFO *pkcs11Info, CK_OBJECT_HANDLE *hObject,
						 const CK_ATTRIBUTE *objectTemplate,
						 const CK_ULONG templateCount )
	{
	return( findDeviceObjects( pkcs11Info, hObject, 
							   objectTemplate, templateCount, FALSE ) );
	}

/* Find a certificate object based on various search criteria:
   
	- Find a certificate matching a given label - certFromLabel()
	- Find a certificate matching a given ID - certFromID()
	- Find a certificate matching the ID of an object hObject - certFromObject()
	- Find a certificate matching a supplied template - certFromTemplate()
	- Find any X.509 certificate - certFromLabel(), no label supplied.

  These are general-purpose functions whose behaviour can be modified through
  the following action codes */

typedef enum {
	FINDCERT_NORMAL,		/* Instantiate standard a certificate+context */
	FINDCERT_DATAONLY,		/* Instantiate data-only certificate */
	FINDCERT_P11OBJECT		/* Return handle to PKCS #11 object */
	} FINDCERT_ACTION;

static int getCertChain( PKCS11_INFO *pkcs11Info, 
						 const CRYPT_DEVICE iCertSource, 
						 const CK_OBJECT_HANDLE hCertificate, 
						 CRYPT_CERTIFICATE *iCryptCert, 
						 const BOOLEAN createContext );

static int findCertFromLabel( PKCS11_INFO *pkcs11Info,
							  const CRYPT_DEVICE iCertSource, 
							  const CK_ATTRIBUTE_TYPE labelType,
							  const char *label, const int labelLength,
							  CRYPT_CERTIFICATE *iCryptCert,
							  const FINDCERT_ACTION findAction )
	{
	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
	CK_ATTRIBUTE certTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
		{ CKA_LABEL, NULL, 0 }
		};
	CK_OBJECT_HANDLE hCertificate;
	int cryptStatus;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isHandleRangeValid( iCertSource ) );
	assert( ( label == NULL && labelLength == 0 ) || \
			isReadPtr( label, labelLength ) );
	assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );

	*iCryptCert = CRYPT_ERROR;

	/* Try and find the certificate with the given label.  Usually this is 
	   the CKA_LABEL but it can also be something like a CKA_URL */
	if( label != NULL )
		{
		certTemplate[ 2 ].type = labelType;
		certTemplate[ 2 ].pValue = ( CK_VOID_PTR ) label;
		certTemplate[ 2 ].ulValueLen = labelLength;
		}
	cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 
							  ( label == NULL ) ? 2 : 3 );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );
	if( findAction == FINDCERT_P11OBJECT )
		{
		*iCryptCert = hCertificate;
		return( CRYPT_OK );
		}

	return( getCertChain( pkcs11Info, iCertSource, hCertificate, iCryptCert, 
						  ( findAction == FINDCERT_NORMAL ) ? TRUE : FALSE ) );
	}

static int findCertFromID( PKCS11_INFO *pkcs11Info,
						   const CRYPT_DEVICE iCertSource, 
						   const void *certID, 
						   const int certIDlength,
						   CRYPT_CERTIFICATE *iCryptCert,
						   const FINDCERT_ACTION findAction )
	{
	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
	CK_ATTRIBUTE certTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
		{ CKA_ID, ( CK_VOID_PTR ) certID, certIDlength }
		};
	CK_OBJECT_HANDLE hCertificate;
	int cryptStatus;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isHandleRangeValid( iCertSource ) );
	assert( isReadPtr( certID, certIDlength ) );
	assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );

	*iCryptCert = CRYPT_ERROR;

	/* Try and find the certificate with the given ID */
	cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );
	if( findAction == FINDCERT_P11OBJECT )
		{
		*iCryptCert = hCertificate;
		return( CRYPT_OK );
		}

	return( getCertChain( pkcs11Info, iCertSource, hCertificate, iCryptCert, 
						  ( findAction == FINDCERT_NORMAL ) ? TRUE : FALSE ) );
	}

static int findCertFromObject( PKCS11_INFO *pkcs11Info,
							   const CRYPT_DEVICE iCertSource, 
							   const CK_OBJECT_HANDLE hObject, 
							   CRYPT_CERTIFICATE *iCryptCert,
							   const FINDCERT_ACTION findAction )
	{
	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
	CK_ATTRIBUTE idTemplate = \
		{ CKA_ID, NULL_PTR, 0 };
	CK_RV status;
	BYTE buffer[ MAX_BUFFER_SIZE + 8 ], *bufPtr = buffer;
	int cryptStatus;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isHandleRangeValid( iCertSource ) );
	assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );

	*iCryptCert = CRYPT_ERROR;

	/* We're looking for a certificate whose ID matches the object, read the 
	   key ID from the device.  We can't use a dynBuf for this because it's a 
	   PKCS #11 attribute rather than a cryptlib attribute */
	status = C_GetAttributeValue( pkcs11Info->hSession, hObject, 
								  &idTemplate, 1 );
	if( status == CKR_OK )
		{
		if( idTemplate.ulValueLen > MAX_BUFFER_SIZE && \
			( bufPtr = clAlloc( "findCertFromObject", \
						( size_t ) ( idTemplate.ulValueLen ) ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		idTemplate.pValue = bufPtr;
		status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
									  &idTemplate, 1 );
		}
	if( status != CKR_OK )
		{
		if( bufPtr != buffer )
			clFree( "findCertFromObject", bufPtr );
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_NOTFOUND ) );
		}

	/* Look for a certificate with the same ID as the key */
	cryptStatus = findCertFromID( pkcs11Info, iCertSource, bufPtr, 
								  idTemplate.ulValueLen, iCryptCert, 
								  findAction );
	if( bufPtr != buffer )
		clFree( "findCertFromObject", bufPtr );
	return( cryptStatus );
	}

static int findCertFromTemplate( PKCS11_INFO *pkcs11Info,
								 const CRYPT_DEVICE iCertSource, 
								 const CK_ATTRIBUTE *findTemplate,
								 const int templateCount,
								 CRYPT_CERTIFICATE *iCryptCert,
								 const FINDCERT_ACTION findAction )
	{
	CK_OBJECT_HANDLE hCertificate;
	int cryptStatus;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isHandleRangeValid( iCertSource ) );
	assert( isReadPtr( findTemplate, \
					   sizeof( CK_ATTRIBUTE ) * templateCount ) );
	assert( templateCount > 0 );
	assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );

	*iCryptCert = CRYPT_ERROR;

	/* Try and find the certificate from the given template */
	cryptStatus = findObject( pkcs11Info, &hCertificate, findTemplate, 
							  templateCount );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );
	if( findAction == FINDCERT_P11OBJECT )
		{
		*iCryptCert = hCertificate;
		return( CRYPT_OK );
		}

	return( getCertChain( pkcs11Info, iCertSource, hCertificate, iCryptCert, 
						  ( findAction == FINDCERT_NORMAL ) ? TRUE : FALSE ) );
	}

/* Find an object from a source object by matching ID's.  This is used to
   find a key matching a certificate, a public key matching a private key, 
   or other objects with similar relationships */

static int findObjectFromObject( PKCS11_INFO *pkcs11Info,
								 const CK_OBJECT_HANDLE hSourceObject, 
								 const CK_OBJECT_CLASS objectClass,
								 CK_OBJECT_HANDLE *hObject )
	{
	CK_ATTRIBUTE keyTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &objectClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_ID, NULL_PTR, 0 }
		};
	CK_ATTRIBUTE idTemplate = \
		{ CKA_ID, NULL_PTR, 0 };
	CK_RV status;
	BYTE buffer[ MAX_BUFFER_SIZE + 8 ], *bufPtr = buffer;
	int cryptStatus;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );

	*hObject = CK_OBJECT_NONE;

	/* We're looking for a key whose ID matches that of the source object, 
	   read its certificate ID.  We can't use a dynBuf for this because it's 
	   a PKCS #11 attribute rather than a cryptlib attribute */
	status = C_GetAttributeValue( pkcs11Info->hSession, hSourceObject, 
								  &idTemplate, 1 );
	if( status == CKR_OK )
		{
		if( idTemplate.ulValueLen > MAX_BUFFER_SIZE && \
			( bufPtr = clAlloc( "findObjectFromObject", \
						( size_t ) ( idTemplate.ulValueLen ) ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		idTemplate.pValue = bufPtr;
		status = C_GetAttributeValue( pkcs11Info->hSession, hSourceObject,
									  &idTemplate, 1 );
		}
	if( status != CKR_OK )
		{
		if( bufPtr != buffer )
			clFree( "findObjectFromObject", bufPtr );
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_NOTFOUND ) );
		}

	/* Find the key object with the given ID */
	keyTemplate[ 1 ].pValue = bufPtr;
	keyTemplate[ 1 ].ulValueLen = idTemplate.ulValueLen;
	cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
	if( bufPtr != buffer )
		clFree( "findObjectFromObject", bufPtr );
	return( cryptStatus );
	}

/****************************************************************************
*																			*
*						 	Certificate R/W Routines						*
*																			*
****************************************************************************/

/* Instantiate a certificate object from a handle */

static int instantiateCert( PKCS11_INFO *pkcs11Info, 
							const CK_OBJECT_HANDLE hCertificate, 
							CRYPT_CERTIFICATE *iCryptCert,
							const BOOLEAN createContext )
	{

⌨️ 快捷键说明

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