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

📄 pgptokenlib.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 5 页
字号:
	}

	memcpy( output->keyid, id, KEYIDLEN);
	output->alg = kPGPPublicKeyAlgorithm_RSA;	/* for now */

	PGP_TOKEN_HANDLE_OK( output->handle );
	
	return TRUE;
}

/*
	Get an array of KeyIDs for which we have PGP Public Key Data object. 

	Go through all PGP Public Key CKO_DATA objects and collect 
	KeyIDs. 
*/
static PGPTokenKeyInfo* sGetPubKeyIDsFromPgpData(
				PGPToken *tptr, 
				/* PGPTokenKeyInfo *p, int p_n,  */
				PGPSize *n)
{
	CK_RV rv;
	CK_OBJECT_HANDLE *handles = NULL;
	int howmany;

	pgpPubKeyDataLabel value;
	const int prefixLen = sizeof(labelPrefix) -1;
	CK_CHAR *keyIdHead = value + prefixLen;

	const CK_OBJECT_CLASS obj = CKO_DATA;
	CK_ATTRIBUTE searchTemplate[] =
	{
		{ CKA_CLASS, (CK_OBJECT_CLASS *)&obj, sizeof(obj) },
		{ CKA_APPLICATION, (CK_CHAR *)application, sizeof(application) - 1 }
	};

	CK_ATTRIBUTE dataTemplate[] = 
	{
		{ CKA_LABEL, &value, sizeof(value)-1 }
	};

	PGPUInt32 sizeData = sizeof(dataTemplate) / sizeof(dataTemplate[0]);

	pgpTokenKeyInfoPriv *out=NULL;
	int out_size = 0;

	int i;

	PGP_TOKEN_TRACE("sGetPubKeyIDsFromPgpData");

	*n = 0;
	handles = sFindP11Objs( tptr, searchTemplate, sizeof(searchTemplate), &howmany, NULL, 0 );
	if( handles == NULL )
		return NULL;

	for( i=0; i<howmany; i++ )  {
		memset( value, 0, sizeof(value) );

		rv = F->C_GetAttributeValue(tptr->session, handles[i], dataTemplate, sizeData);
		if (rv != CKR_OK)  {
			PGP_TOKEN_TRACE( "C_GetAttributeValue falied" );
			break;
		}

		if( strncmp( value, labelPrefix, prefixLen ) == 0 )  {
			PGPByte *p;
			PGPByte *in = keyIdHead;

			out = (out==NULL) ? 
				malloc( sizeof(pgpTokenKeyInfoPriv) ) : realloc( out, (out_size+1)*sizeof(pgpTokenKeyInfoPriv));

			/* Convert hex string to bytes */
			for( p = out[out_size].keyid; 
                    p<out[out_size].keyid + KEYIDLEN; p++ )  {
				PGPByte b = *in;
				*p = ((b  >= 'A') ?  (b -'A'+10) : (b - '0')) << 4;
				b = *(++in);
				*p |= (b  >= 'A') ?  (b -'A'+10) : (b - '0');
				in ++;
			}

			/* Store handles for optimization */
			out[out_size].handle = handles[i];
			out[out_size].obj_class = CKO_DATA;		/* PGP object */

            /* In this case PKCS11 CKA_ID == KeyID. 
               (certs of this key, as well as a private key 
			   have the same CKA_ID) */
            out[out_size].id_size = KEYIDLEN;
            memcpy( out[out_size].id, out[out_size].keyid, KEYIDLEN );

			out[out_size].pgpData = TRUE;
			out[out_size].alg = kPGPPublicKeyAlgorithm_RSA;	/* for now */

			out_size ++;
		}
	}

	free(handles);

	if( rv != CKR_OK || out == NULL )  {
		free(out);
		out = NULL;
	}

	if( out == NULL )  
		return NULL;

	*n = out_size;
	return (PGPTokenKeyInfo*)out;
}

/* Collect keyIDs from the PKCS11 cert objects 

   This is intended for the browser-generated keys ONLY. 
   We assume here that there is ONLY one X509 certificate
   per public key.

   p is input buffer, allocated with malloc of p_n pgpTokenKeyInfoPriv 
   elements of. This function will reallocs p and returns it.
   If return is NULL, p is freed. 

   Requires public key id cash to be present. 
*/
static PGPTokenKeyInfo* 
sGetPubKeyIDsFromCerts(	PGPToken *tptr, 
						PGPTokenKeyInfo *p, int p_n, 
						int *n_out)
{
	CK_ATTRIBUTE dataTemplate[] = 
	{
		{ CKA_VALUE, NULL, 0 }
	};

	CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
	CK_CERTIFICATE_TYPE certType = CKC_X_509;
		CK_ATTRIBUTE certTemplate[] =
	{
		{ CKA_CLASS, &certClass, sizeof(certClass) },
		{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) }
	};

	CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
	CK_ATTRIBUTE pubTemplate[] =
	{
		{ CKA_ID, NULL, 0 },	/*must be the first*/
		{ CKA_CLASS, &pubClass, sizeof(pubClass) },
	};


	CK_OBJECT_HANDLE *handles = NULL;
	int howmany;
	int i;

	int n = (p==NULL ? 0 : p_n);

	void *data_buf=NULL;
	int data_buf_size=0;

	PGP_TOKEN_TRACE("sGetPubKeyIDsFromCerts");

	*n_out = 0;

	/* Find all cert. objects */
	handles = sFindP11Objs( tptr, certTemplate, sizeof(certTemplate), &howmany, NULL, 0 );
	if( handles == NULL )  
		return p;

	for( i=0; i<howmany; i++ )  {
		/* Find related public key object */
		pgpTokenKeyInfoPriv cert;

		pgpTokenKeyInfoPriv pub; 
		pgpTokenKeyInfoPriv cert2; 

		memset( &cert, 0, sizeof(cert) );
		cert.handle = handles[i];

		/* Try to find a CKO_PUBLIC_KEY, corresponding to certificate. 
		   Then we can easily determine the keyID */
		if( sObjToRelatedObj( tptr, &cert, pubTemplate, sizeof(pubTemplate), &pub ) )  {
		    /* Now, see if this certificate is on the PGP key. In that case
			   pub.id will be a keyid as well */
			if( sKeyIDToKeyInfoFromCache( tptr, pub.id, (pgpTokenKeyInfoPriv*)p, p_n, NULL, FALSE ) )  {
				PGP_TOKEN_TRACE("Already in the cache");
				continue;
			}
			
			p = ( p == NULL ) ? malloc( sizeof(pgpTokenKeyInfoPriv) ) :
				realloc( p, (n+1)*sizeof(pgpTokenKeyInfoPriv) );
			
			if( !sGetAllKeyInfo( tptr, &pub, (pgpTokenKeyInfoPriv*)p+n,  
					&data_buf, &data_buf_size ) )
				break;

			((pgpTokenKeyInfoPriv*)p+n)->obj_class = CKO_PUBLIC_KEY;
			
			/* No PGP DATA for this keyid */
			((pgpTokenKeyInfoPriv*)p+n)->pgpData = FALSE;

			PGP_TOKEN_TRACE1( "sGetPubKeyIDsFromCerts: %x key added (pub.key-based)", *(unsigned*)pub.keyid );
			
			n++;
		}	
		else if( sCertToKeyID &&
			sObjToRelatedObj( tptr, &cert, pubTemplate, sizeof(pubTemplate[0]), &cert2 ) )  
		{
			/* No public key associated with certificate. Get key ID from the 
		           certificate using PGPSDK */
			
			PGPSize size;
			PGPByte *c = sGetP11Value( tptr, cert2.handle, &size );
			PGPUInt32 alg; 

			pgpAssert( *(PGPUInt32*)cert2.id && cert2.id_size>0 );

			if( (*sCertToKeyID)( c, size, kPGPInputFormat_PEMEncodedX509Cert, 
				cert2.keyid, &alg, sCertToKeyID_param ) && 
				alg == kPGPPublicKeyAlgorithm_RSA )
			{
				p = ( p == NULL ) ? malloc( sizeof(pgpTokenKeyInfoPriv) ) :
					realloc( p, (n+1)*sizeof(pgpTokenKeyInfoPriv) );

				pgpAssert( *(PGPUInt32*)(cert2.keyid) != 0 );
				pgpAssert( ((PGPUInt32*)(cert2.keyid))[1] != 0 );

				memcpy( (pgpTokenKeyInfoPriv*)p+n, &cert2, sizeof(cert2) );

				((pgpTokenKeyInfoPriv*)p+n)->obj_class = CKO_CERTIFICATE;
				((pgpTokenKeyInfoPriv*)p+n)->alg = kPGPPublicKeyAlgorithm_RSA;	/* for now */
			
				/* No PGP DATA for this keyid */
				((pgpTokenKeyInfoPriv*)p+n)->pgpData = FALSE;

				PGP_TOKEN_TRACE1( "sGetPubKeyIDsFromCerts: %x key added (cert-based)", *(unsigned*)cert2.keyid );
			
				n++;
			}

			free(c);
		}
		else  {
			continue;	/* ignore this object */
		}
	}

	free( handles );
	free( data_buf );

	if( i != howmany )  {	/* We had some errors */
		free( p );
		return NULL;
	}

	PGP_TOKEN_TRACE1("%d browser-generated objects found", n-p_n);

	*n_out = n-p_n;
	return (PGPTokenKeyInfo*)p;
}

static void sTrim( PGPByte *s, int size )  {
    PGPByte *p;
    
    if( *s == '\0' )
        return;

    for( p = s + size-1; p >= s; p-- )  {
        if( *p == ' ' )
            *p = '\0';
        else
            break;
    }

    return;
}

static PGPBoolean
sP11TokenInfo( const PGPUInt32 slot, PGPTokenInfo *info )
{
	CK_RV rv;
	CK_TOKEN_INFO tinfo;

#if PGP_DEBUG
    CK_SLOT_INFO sinfo;

    memset( &sinfo, 0, sizeof(sinfo) );
    rv = F->C_GetSlotInfo(slot, &sinfo);
    if( rv != CKR_OK  ) {
        pgpDebugMsg( "C_GetSlotInfo failed" );
        return FALSE;
    }

    if( !(sinfo.flags & CKF_TOKEN_PRESENT) )   {
        PGP_TOKEN_TRACE( "sP11TokenInfo: token is not present" );
        return FALSE;
    }
#endif

    memset( &tinfo, 0, sizeof(tinfo) );
    rv = F->C_GetTokenInfo(slot, &tinfo);
    if( rv != CKR_OK ) {
        pgpDebugMsg( "C_GetTokenInfo failed" );
        return FALSE;
    }

    info->size = sizeof( *info );

    sTrim( tinfo.manufacturerID, sizeof(tinfo.manufacturerID) );
    sTrim( tinfo.model, sizeof(tinfo.model) );
    sTrim( tinfo.serialNumber, sizeof(tinfo.serialNumber) );

    strncpy( info->manufacturerID, tinfo.manufacturerID, sizeof(info->manufacturerID)-1 );
    info->manufacturerID[sizeof(info->manufacturerID)-1] = '\0';
    strncpy( info->model, tinfo.model, sizeof(info->model)-1 );
    info->model[sizeof(info->model)-1] = '\0';
    strncpy( info->serialNumber, tinfo.serialNumber, sizeof(info->serialNumber)-1 );
    info->serialNumber[sizeof(info->serialNumber)-1] = '\0';

    info->minPinLen = tinfo.ulMinPinLen;
    info->maxPinLen = tinfo.ulMaxPinLen;

    return TRUE;
}

/* Get the range for the keysize, supported by the RSA key generation 
   mechanism
 */
PGPBoolean static 
sGetRsaKeySizeRange(PGPUInt32 slot, PGPTokenInfo *info)
{
	CK_RV rv;
	int nMechanisms=0;
	int nMechanisms2;
	CK_MECHANISM_TYPE *pMechList = NULL;
	int i;

	info->bRsa = FALSE;
	info->minRsaKeySize = info->maxRsaKeySize = 0;

	rv = F->C_GetMechanismList(slot, (CK_MECHANISM_TYPE_PTR)NULL, &nMechanisms);
	pgpAssert( rv == CKR_OK );
	if( nMechanisms == 0 )  {
		PGP_TOKEN_TRACE( "sGetRsaKeySizeRange: no key generation mechanisms" );
		return FALSE;
	}

	pMechList = calloc( sizeof(CK_MECHANISM_TYPE), nMechanisms );
	if( pMechList == NULL )
		return FALSE;

	rv = F->C_GetMechanismList(slot, pMechList, &nMechanisms2);
	if( rv != CKR_OK )  {
		pgpDebugMsg( "GetMechanismList failed" );
		free( pMechList );
		return FALSE;
	}

	pgpAssert(nMechanisms == nMechanisms2);


	for( i=0; i<nMechanisms; i++ )  {
		/* Get only RSA for now */
		if( pMechList[i] == CKM_RSA_PKCS_KEY_PAIR_GEN )  {
			break;
		}
	}
	free( pMechList );

	if( i == nMechanisms )
		return TRUE; /* No key generation. Card can still be used in read-only mode */

	/* Card supports CKM_RSA_PKCS_KEY_PAIR_GEN. Get deatils. */
	{
		CK_MECHANISM_INFO minfo;

		(void)memset(&minfo, 0, sizeof(CK_MECHANISM_INFO));
		rv = F->C_GetMechanismInfo(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &minfo);
		if( rv != CKR_OK ) {
			pgpDebugMsg( "C_GetMechanismInfo failed for supported mechanism" );
			return FALSE;
		}

		/* Double check */
		if( !( minfo.flags & CKF_GENERATE_KEY_PAIR ) )  {
			pgpDebugMsg( "Inconsistency: mechanism expected to "
				"allow the key generation, but appropriate flag is not set" );
			return FALSE;
		}

		info->bRsa = TRUE;
		info->minRsaKeySize = minfo.ulMinKeySize;
		info->maxRsaKeySize = minfo.ulMaxKeySize;
	}

	return TRUE;
}

static CK_RV sP11OpenSession( PGPToken *tptr ) {
	CK_RV rv;

	if (tptr->have_slot)
		rv = F->C_OpenSession(tptr->slot, CKF_RW_SESSION | CKF_SERIAL_SESSION,
			                  0/*tptr*/, NULL/*sP11Callback*/, &(tptr->session));
	else return CKR_SLOT_ID_INVALID;

	if (rv != CKR_OK)	{
		tptr->session = 0;
		tptr->have_session = FALSE;
		PGP_TOKEN_TRACE( "C_OpenSession failed" );

		return rv;
	}

	tptr->have_session = TRUE;
	return CKR_OK;
}

static CK_RV sP11CloseSession( PGPToken *tptr ) {
	CK_RV rv;

	if (!tptr->have_session)
		return CKR_OK;

	rv = F->C_CloseSession( tptr->session );

#if PGP_DEBUG
	if( rv != CKR_OK )
		pgpDebugMsg( "CloseSession failed" );
#endif

	tptr->session = 0;
	tptr->have_session = FALSE;

	return rv;
}

/* Copies KEYIDs from the cache to the buffer to be freed by the 
   caller. 
   Implemenation of this finction can be made dummy, if copying 
   not needed later. 
 */
static PGPTokenKeyInfo *sDupKeyIDs( const PGPTokenKeyInfo *in, int n )  
{
	pgpTokenKeyInfoPriv *out;

	pgpAssert( n && in );
	out = calloc( sizeof( pgpTokenKeyInfoPriv ), n );

	if( out )
		memcpy( out, in, n * sizeof( pgpTokenKeyInfoPriv ) );

	return (PGPTokenKeyInfo*)out;
}

/* Prepare key infos in the ascending order of the first 
   sizeof(unsigned) bytes of keyid */
static void sPrepareForCache( PGPToken *tptr, 
	pgpTokenKeyInfoPriv *ki, int n )
{
	pgpTokenKeyInfoPriv last;
	pgpTokenKeyInfoPriv *p_last;
	unsigned last_value;

	unsigned curr;

	int changed;

	int i,j;

	if( n == 0 || ki == NULL )  {
		PGP_TOKEN_TRACE("sPrepareForCache: nothing to prepare");
		return;
	}

	tptr->cachedTimeStamp = -1;

	/* Sort key infos */
	for( i=0; i<n; i++ )  {
		p_last = ki+i;
		last_value = *(unsigned*)p_last->keyid;
		changed = FALSE;

		for( j=i+1; j<n; j++ )  {
			curr = *(unsigned*)(ki+j)->keyid;
			
			if( curr < last_value )  {
				last_value = curr;

⌨️ 快捷键说明

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