📄 pgptokenlib.c
字号:
}
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 + -