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

📄 pgptokenlib.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 5 页
字号:
		memcpy( output->id, templ[0].pValue, size );
	}
	else  {		/* was called to determine ID */
		memcpy( output->id, pID, size );
		output->id_size = size;

		output->handle = input->handle;
		output->obj_class = input->obj_class;
	}

	if( !isID )
		free( pID );

	return TRUE;
}

/* Get private key info, corresponding to the public object (public key or certificate) */
PGPBoolean static 
sPubToPriv( PGPToken *tptr, 
			const pgpTokenKeyInfoPriv *pub, 
			pgpTokenKeyInfoPriv *priv )  
{
	CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
	CK_BBOOL ktTrue = TRUE;
	CK_KEY_TYPE keyType = CKK_RSA;
	CK_ATTRIBUTE privTemplate[] =
	{
		{ CKA_ID, NULL, 0 },	/* must be the first */
		{ CKA_CLASS, &privClass, sizeof(privClass) },
		{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
		{ CKA_TOKEN, &ktTrue, 1 }
	};

	return sObjToRelatedObj( tptr, pub, 
		privTemplate, sizeof(privTemplate), priv );
}

#if PGP_DEBUG
int sCacheIsSorted(const PGPTokenKeyInfo *cache, int n)  {
	int i; 
	int j;
	unsigned smallest;

	for( i=0; i<n; i++ )  {
		smallest = *(unsigned*)cache[i].keyid;

		for( j=i+1; j<n; j++ )  {
			if( smallest > *(unsigned*)cache[j].keyid )  {
				PGP_TOKEN_TRACE2("Sorting problem: [%d] > [%d]", i, j );
				return 0;
			}
		}
	}

	return 1;
}
#endif

static PGPBoolean sKeyIDToKeyInfoFromCache(
				PGPToken *tptr, const PGPByte *keyID,
				pgpTokenKeyInfoPriv *cache, int n, 
				pgpTokenKeyInfoPriv *ki, PGPBoolean is_private )
{
	int i;
	const unsigned keyID_u = *(unsigned*)keyID;

	int start_i=0;
	int end_i;

	PGPBoolean found=FALSE;

	if( ki )
		memset( ki, 0, sizeof(*ki) );

	if( !n )
		return FALSE;

	pgpAssert( sCacheIsSorted((PGPTokenKeyInfo*)cache, n) );

	end_i = n-1;

	pgpAssert( keyID_u != 0 );

	/* Perform binary search */
	while( end_i - start_i > 1 )  {
		const middle = start_i + (end_i - start_i) / 2;
		const unsigned u = *(unsigned*)cache[middle].keyid;

		if( keyID_u > u )  {
			start_i = middle;
		}
		else if( keyID_u < u )  {
			end_i  = middle;
		}
		else  {
			break;
		}

		pgpAssert( end_i >= start_i );
	}

	pgpAssert( start_i <= end_i );

	for (i = start_i ; i <= end_i; i ++)  {
		if( memcmp(keyID, cache[i].keyid, sizeof(cache[i].keyid))==0 ) {
			found = TRUE;
			break;
		}
	}

	if( !found )  {
		PGP_TOKEN_TRACE1( "sKeyIDToKeyInfoFromCache(keyID=%x): not found", *(unsigned*)keyID );
		return FALSE;
	}

	if( ki )  {
		if( is_private )  {
			PGPBoolean ret;
			
			ret = sPubToPriv( tptr, cache+i, ki );

			if( !ret )  {
				PGP_TOKEN_TRACE1(
					"sKeyIDToKeyInfoFromCache: private key %x doesn't exist "
					"(the guess based on public key was wrong)", *(unsigned*)(cache[i].keyid) );

				/* zero keyid to be purged later */ 
				memset( cache[i].keyid, 0, sizeof(cache[i].keyid) );

				return FALSE;
			}
		}
		else   {
			memcpy( ki, cache+i, sizeof(*ki) );
			PGP_TOKEN_HANDLE_OK( ki->handle );
		}
	}

	pgpAssert( ! ki || memcmp( ki->keyid, keyID, sizeof(ki->keyid) )==0 );

	return TRUE;
}


/* purge cache from items with zero keyids */
static void sPurgeCache( PGPTokenKeyInfo * const ki, PGPSize *size )  {
	PGPByte last_keyid[8];
	int insize = (int)*size;
	PGPTokenKeyInfo * ki2 = ki;
	int i;

	if( ki==NULL || size==0 )
		return;

	memset( last_keyid, 0, sizeof(last_keyid) );

	/* check all but last */
	for( i=0; i<insize-1; i++ )  {
		if( *(unsigned*)ki2->keyid == 0 && 
			memcmp(ki2->keyid, last_keyid, sizeof(last_keyid))==0 )  
		{
			memcpy( ki2, ki2+1, sizeof(*ki2) );

			insize--;
		}
		else
			ki2++;
	}

	/* check the last */
	if( *(unsigned*)ki2->keyid == 0 && 
		memcmp(ki2->keyid, last_keyid, sizeof(last_keyid))==0 )  
	{
		insize--;
	}

	pgpAssert( sCacheIsSorted( ki, insize ) );

	pgpAssert( insize >= 0 );

	*size = (PGPSize)insize;
}

/*
  Return TRUE if the given token holds the given key.
  If ki is not NULL, fill it with information about that key.
  Two cases possible in the latter case:
  we need handle to the CKO_PUBLIC_KEY (is_private=FALSE) or
  we need handle to the CKO_SECRET_KEY key (is_private=TRUE)
 */
static PGPBoolean sKeyIDToPrivKeyInfo(PGPToken *tptr, const PGPByte *keyID,
				pgpTokenKeyInfoPriv *ki, PGPBoolean is_private)
{
	PGPUInt32 n;
	pgpTokenKeyInfoPriv *block;
	const unsigned keyID_u = *(unsigned*)keyID;

	PGP_TOKEN_TRACE2( "sKeyIDToPrivKeyInfo(keyID=%x, is_private=%d)", 
		*(unsigned*)keyID, is_private );

	/* Always look for details in priv key info, because it is the largest set */
	block = (pgpTokenKeyInfoPriv *)sGetPrivKeyIDs(tptr, &n, FALSE);

#if PGP_DEBUG
	if( !block || !n )
		PGP_TOKEN_TRACE("No keys in cache");
#endif

	if( sKeyIDToKeyInfoFromCache( tptr, keyID, block, n, ki, is_private ) )  {
		return TRUE;
	}
	else  {	/* there is a possibility that cache was changed */
		if( is_private )
			sPurgeCache( tptr->privKeyIDs, &tptr->nPrivKeyIDs );
		else
			sPurgeCache( tptr->pubKeyIDs, &tptr->nPubKeyIDs );

		return FALSE;
	}
}


/*
	Returns handle to the "PGP Public Key Data", which is a set of signed UserIDs, 
	without the PGP Public Key packet. 
*/
static PGPBoolean sKeyIDToPubKeyInfo(PGPToken *tptr, const PGPByte *keyID,
								 pgpTokenKeyInfoPriv *ki )
{
	PGPUInt32 n = 0;
	pgpTokenKeyInfoPriv *block;

	PGP_TOKEN_TRACE1( "sKeyIDToPubKeyInfo(keyID=%x)", *(unsigned*)keyID );

	block = (pgpTokenKeyInfoPriv *)sGetPubKeyIDs(tptr, &n, FALSE);

	return sKeyIDToKeyInfoFromCache( tptr, keyID, block, n, ki, FALSE );
}

/* Returns content of CKA_VALUE for the given handle */
static PGPByte *
sGetP11Value( PGPToken *tptr, CK_OBJECT_HANDLE handle, PGPSize *size )  {
	PGPByte *value;
	CK_RV rv;
	CK_ATTRIBUTE dataTemplate = { CKA_VALUE, NULL, 0 };
    int mapSize;
	
    PGPByte *pubKeyPktOut=NULL;
	int len_out=0;

	PGP_TOKEN_TRACE("sGetP11Value");

	rv = F->C_GetAttributeValue(tptr->session, handle, &dataTemplate, 1 );
	if (rv != CKR_OK)
	{
	    pgpDebugMsg( "C_GetAttributeValue failed" );
		return NULL;
	}
		
	mapSize = dataTemplate.ulValueLen;
	if( mapSize == 0 )
		return NULL;

	value = malloc( mapSize );
	pgpAssert(value);

    dataTemplate.pValue = value;

	rv = F->C_GetAttributeValue(tptr->session, handle, &dataTemplate, 1);
	if (rv != CKR_OK)
	{
	    pgpDebugMsg( "C_GetAttributeValue failed" );
		free(value);
		value = NULL;
	}

    *size = mapSize;
    return value;
}

/* 
	Create PGP Public Key Packet from the PKCS11 CKO_PUBLIC_KEY object.
	Caller must free di.
*/
static PGPError 
sGetP11PubKey( PGPToken *tptr, PGPByte *keyID, pgpTokenPubKeyStub *keyStub,
			   pgpTokenDataInfo **di )  
{
	CK_RV rv;
	pgpTokenKeyInfoPriv ki; 

	*di = NULL;

	/* Try to find CKO_PUBLIC_KEY */
	sKeyIDToPrivKeyInfo( tptr, keyID, &ki, FALSE );

	if( ki.handle == (CK_OBJECT_HANDLE)NULL )  {
		PGP_TOKEN_TRACE("No PKCS11 public key objects found");
		return kPGPError_NoErr;
	}

	/* Here we have the handle, referencing the CKO_PUBLIC_KEY object */
	{
        PGPByte *buf;
		PGPByte *mod_buf;
		PGPByte *exp_buf;
		PGPUInt32 mod_size;
		PGPUInt32 exp_size;

		CK_ATTRIBUTE dataTmpl[] = 
		{
			{ CKA_MODULUS,			NULL, 0 },
			{ CKA_PUBLIC_EXPONENT,	NULL, 0 }
		};

		rv = F->C_GetAttributeValue(tptr->session, ki.handle, dataTmpl, 2);
		
		mod_size = dataTmpl[0].ulValueLen;
		exp_size = dataTmpl[1].ulValueLen;

		buf = calloc( sizeof(pgpTokenDataInfo) + mod_size + exp_size, 1 );
		if( IsNull( buf ) )
			return kPGPError_OutOfMemory;

        exp_buf = buf + sizeof(pgpTokenDataInfo);   /* Exponent first */
		mod_buf = exp_buf + exp_size;               /* Modulus next */

		dataTmpl[0].pValue = mod_buf;
		dataTmpl[1].pValue = exp_buf;

		rv = F->C_GetAttributeValue(tptr->session, ki.handle, dataTmpl, 2);
		if (rv != CKR_OK) {
			pgpDebugMsg( "C_GetAttributeValue failed" );
			free( buf );
			return kPGPError_SmartCardError;
		}

        {
            pgpTokenDataInfo *p = (pgpTokenDataInfo*)buf;
            p->alg = kPGPPublicKeyAlgorithm_RSA;
            p->exp_size = exp_size;
            p->mod_size = mod_size;

            memcpy( &(p->pubKeyStub), keyStub, sizeof(p->pubKeyStub) );
        }

        *di = (pgpTokenDataInfo *)buf;
	}

	return kPGPError_NoErr;
}


/* Get missing key info from the given partially defined key object
   
   buffer is temporary buffer, allocated/reallocated in this routine 
*/
static PGPBoolean 
sGetAllKeyInfo( PGPToken *tptr, 
				const pgpTokenKeyInfoPriv *input, 
				pgpTokenKeyInfoPriv *output,
				void **buffer, int *buffer_size )
{
	CK_RV rv;

	const CK_OBJECT_HANDLE handle = input->handle;
	const PGPBoolean isID = (PGPBoolean)input->id_size;
	const PGPBoolean isKeyID = *(unsigned*)input->keyid;

	CK_ATTRIBUTE modTemplate[] =
	{
		{ CKA_MODULUS, NULL, 0 },
		{ CKA_LABEL, NULL, 0 },
		{ CKA_ID, NULL, 0 }		/* Must be last */
	};
	int modTemplateSize = sizeof(modTemplate)/sizeof(modTemplate[0]);

	PGPByte *b = *buffer;
	int b_size = *buffer_size;
	int cur_len_mod, cur_len_id, cur_len_label, cur_len_sum;
	PGPByte *label;
	const PGPByte *id;

	pgpTokenKeyInfoPriv *p_out_temp=NULL;
	int p_out_temp_size=0;

	if( handle == (CK_OBJECT_HANDLE)NULL )  {
		memset( output, 0, sizeof(*output) );
		pgpAssert( 0 );
		return FALSE;
	}

	PGP_TOKEN_HANDLE_OK( handle );

	memcpy( output, input, sizeof(*output) );

	if( isID )  {
		if( isKeyID )  {
			PGP_TOKEN_TRACE("sGetAllKeyInfo: object already complete");
			return TRUE;	/* We know everything */
		}
		modTemplateSize --;		/* We know ID */
	}

	rv = F->C_GetAttributeValue(tptr->session, handle, modTemplate, modTemplateSize);
	if (rv != CKR_OK) {
		pgpDebugMsg( "C_GetAttributeValue failed: no MODULUS" );
		return FALSE;
	}

	cur_len_mod = modTemplate[0].ulValueLen;
	cur_len_label = modTemplate[1].ulValueLen;

	if( isID )
		cur_len_id = 0;
	else
		cur_len_id = modTemplate[2].ulValueLen;

	cur_len_sum = cur_len_mod + cur_len_id + cur_len_label;

	pgpAssert( cur_len_mod > 8 );
	if( cur_len_sum > b_size )  {
		b = (b==NULL) ? 
			malloc( cur_len_sum ) :
		    realloc( b, b_size + cur_len_sum );

		if( b == NULL )  {
			*buffer = NULL;
			*buffer_size = 0;
			return FALSE; /* kPGPError_OutOfMemory */;
		}

		b_size += cur_len_sum;

		*buffer = b;
		*buffer_size = b_size;
	}

	modTemplate[0].pValue = b;
	label = modTemplate[1].pValue = b + cur_len_mod;
	if( isID )  
		id = input->id;
	else
		id = modTemplate[2].pValue = label + cur_len_label;

	rv = F->C_GetAttributeValue(tptr->session, handle, modTemplate, modTemplateSize);
	if (rv != CKR_OK)  {
		pgpDebugMsg( "C_GetAttributeValue failed" );
		return FALSE;
	}

    /* Store CKA_ID for later */
	if( !isID )  {  /* ID was not given */
        const label_longer = (cur_len_id >= sizeof(output->id));

        memcpy( output->id, id, 
            label_longer ? sizeof(output->id) : cur_len_id );

        if( !label_longer )  {	
            memset( output->id+cur_len_id, 0, sizeof(output->id)-cur_len_id );
            output->id_size = cur_len_id;
        }
#if PGP_DEBUG
        else if( cur_len_id == sizeof(output->id) ) {
            output->id_size = sizeof(output->id);
        }
#endif
        else  {
            pgpAssert(0);
            /* We should work in this case, but I have never seen this. */
            output->id_size = sizeof(output->id);
        }
    }

	output->pgpData = TRUE;

    /* Compare labels to see if this is a PGP token */
	if( (cur_len_id > ID_LEN_MAX) /* never seen it */ ||
        ( ( cur_len_label != sizeof(labelPub)-1 || 
		    memcmp( label, labelPub, sizeof(labelPub)-1 )!=0 ) &&
          ( cur_len_label != sizeof(labelPubSub)-1 || 
		    memcmp( label, labelPubSub, sizeof(labelPubSub)-1 )!=0 ) ) )
	{
		/* not a PGP token -- take last KEYIDLEN bytes as keyid */
		id = (PGPByte*)b+cur_len_mod - KEYIDLEN; 
		PGP_TOKEN_TRACE1( "Not a PGP object keyid=%x", *(unsigned*)id );
		output->pgpData = FALSE;

⌨️ 快捷键说明

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