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

📄 pgptokenlib.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 5 页
字号:
/*____________________________________________________________________________
	Copyright (C) 2002 PGP Corporation
	All rights reserved.

	$Id: pgpTokenLib.c,v 1.92 2002/08/06 20:11:04 dallen Exp $
____________________________________________________________________________*/

#include "pgpSDKBuildFlags.h"

#define PGP_TRACE_P11 1	 /* Extensive logging on the debug console */

#ifndef CRYPTOKIDLL
#define CRYPTOKIDLL "slbck.dll"
#endif

#include "windows.h"

#pragma pack(push, cryptoki, 1)
#include "pkcs11.h"
#pragma pack(pop, cryptoki)

#include "pgpConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pgpTokenLib.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpUsuals.h"

#define KEYIDLEN	    8
#define ID_PADDED_LEN   20
    /* For IE with old "Datakey RSA CSP" 20 is requirement.
       20 is a size Netscape/IE uses (SHA-1) for keys 
	   generated within the browser. 
	   However, 8 works with Netscape 4.7 and 6.0 and IE.
    */
#define ID_LEN_MAX   48	/* This is a maximum I saw */

#if ID_PADDED_LEN < KEYIDLEN || ID_PADDED_LEN > ID_LEN_MAX || KEYIDLEN > ID_LEN_MAX
#error 
#endif

#define CKR_PIN_LOCKED_2 0xA4

#undef pgpAssert
#ifdef PGP_WIN32
#include <assert.h>
#define pgpAssert assert
#else
#define pgpAssert(x)
#endif

#define sCheckCache(tptr)

static CK_FUNCTION_LIST_PTR F;
static PGPToken token[MAXTOKENS];
static PGPBoolean is_CRYPTOKI_initialized = FALSE;
static int s_how_many_tokens = -1;	/* don't know */
static PGPBoolean enable_checking = TRUE;

static PGPUInt32 *now_slots = NULL;
static PGPUInt32 now_slots_allocated = 0;

static PGPByte CryptoKiDll[255] = CRYPTOKIDLL;

static pgpTokenCertToKeyID sCertToKeyID = NULL;
static void *sCertToKeyID_param = NULL;

/*** FORWARD DECLARATIONS ***/

static void			   PKCS11ConstructTokenFields(PGPToken *tptr);
static PGPError		   PKCS11ConstructAllTokenFields(void);
static PGPError		   PKCS11PutPublicData(PGPToken *tptr, PGPByte *keyID,
						   PGPByte *pubKeyBlock, PGPSize size, 
						   pgpTokenDataInfo *di );
static PGPError		   PKCS11PutPrivate(PGPToken *tptr, PGPBoolean is_master, 
                            TCL_PRIVATE_KEY_DATA_LIST);

static PGPError		   PKCS11Delete(PGPToken *tptr, const PGPByte *keyID, PGPBoolean is_last );

static PGPByte *	   PKCS11GetPublicData(PGPToken *tptr, PGPByte *keyID,
							PGPSize *size, pgpTokenDataInfo **di);
static PGPTokenCertInfo * PKCS11GetCerts(PGPToken *tptr, PGPTokenKeyInfo *keyID,
							PGPInt32 *n);
static PGPByte *	   PKCS11GetCert(PGPToken *tptr, PGPTokenCertInfo *certInfo,
							PGPSize *size);

static PGPTokenKeyInfo*sGetPubKeyIDs(PGPToken *tptr, PGPSize *n, PGPBoolean is_dup);
static PGPTokenKeyInfo*PKCS11GetPubKeyIDs(PGPToken *tptr, PGPSize *n);

static PGPTokenKeyInfo*sGetPrivKeyIDs(PGPToken *tptr, PGPSize *n_out, PGPBoolean is_dup );
static PGPTokenKeyInfo*PKCS11GetPrivKeyIDs(PGPToken *tptr, PGPSize *n);

static PGPError        PKCS11Logout(PGPToken *tptr);
static PGPError		   PKCS11Login(PGPToken *tptr, char const *input,
							PGPSize length);
static PGPError		   PKCS11Sign(PGPToken *tptr, CK_BYTE *keyID, CK_BYTE *in,
							PGPSize isize, CK_BYTE *out,
							PGPSize osize);
static PGPError		   PKCS11Decrypt(PGPToken *tptr, CK_BYTE *keyID,
							CK_BYTE *in, PGPSize isize,
							CK_BYTE *out, PGPSize osize);
static PGPError		   PKCS11Destroy(PGPToken *tptr);
static PGPError		   PKCS11Init(PGPToken *tptr, PGPUInt32 whichslot,
							PGPBoolean haveslot, PGPInt32 tokenNum);
static PGPError		   PKCS11Keygen(PGPToken *tptr, PGPByte *ID,
							PGPSize modulusSize, PGPBoolean genMaster, PGPByte *modulus,
							PGPByte *pubExp, PGPSize *pubExpSize );
static PGPError		   PKCS11EditKeyList(PGPToken *tptr, PGPByte *origID,
							PGPByte *newID);
static PGPError		   PKCS11SetPIN(PGPToken *tptr, char *oldPIN,
							PGPSize oldPINsize, char *newPIN,
							PGPSize newPINsize);
static PGPError			PKCS11Wipe(PGPToken *tptr);
static PGPError			PKCS11Format(PGPToken *tptr, 
							PGPByte const *so_pin,		 PGPSize so_pin_len,
							PGPByte const *new_user_pin, PGPSize new_user_pin_len );
static PGPError         PKCS11GetInfo( PGPToken *tptr, 
                            PGPTokenInfo *tokenInfo );
static PGPError         PKCS11ImportX509(PGPToken *tptr, const PGPByte *keyID, 
                            const PGPByte *userID, PGPSize userID_len, 
                            const PGPByte *x509, PGPSize x509_len, 
                            const PGPByte *subjDER, PGPSize  subjDER_len, 
                            const PGPByte *issuerDER, PGPSize issuerDER_len,
                            const PGPByte *sn, PGPSize sn_len );

static PGPError         PKCS11PutKeyContainer( PGPToken *tptr,
                            const PGPByte *keyID, 
                            const PGPByte *uuid, PGPSize uuidSize );
static PGPError         PKCS11GetKeyContainer( PGPToken *tptr,
                            const PGPByte *keyID, 
                            PGPByte **uuidOut, PGPSize *uuidOutSize );

#if defined(PGP_DEBUG) && PGP_DEBUG != 0 && defined(PGP_TRACE_P11)
#include <stdarg.h>
void spgpTokenLibTrace(const char *file, int line, const char *fmt, ...)  {
	va_list marker;
	char s[1024];
	char s2[1024];
	const char *p = strrchr( file, '\\' );

	if( p )  
		file = p+1;

	va_start( marker, fmt );     
	vsprintf( s, fmt, marker );
	va_end( marker ); 
	sprintf( s2, "%s(%d): %s\n", file, line, s );
#ifdef PGP_WIN32	
	OutputDebugString( s2 );
#else
	printf( s2 );	/* TODO: logging for other platforms */
#endif
}
#define PGP_TOKEN_TRACE( s ) spgpTokenLibTrace( __FILE__, __LINE__, s )
#define PGP_TOKEN_TRACE1( s, p1 ) spgpTokenLibTrace( __FILE__, __LINE__, s, p1 )
#define PGP_TOKEN_TRACE2( s, p1,p2 ) spgpTokenLibTrace( __FILE__, __LINE__, s, p1,p2 )
#define PGP_TOKEN_TRACE3( s, p1,p2,p3 ) spgpTokenLibTrace( __FILE__, __LINE__, s, p1,p2,p3 )
#else
#define PGP_TOKEN_TRACE( s ) 
#define PGP_TOKEN_TRACE1( s, p1 ) 
#define PGP_TOKEN_TRACE2( s, p1,p2 ) 
#define PGP_TOKEN_TRACE3( s, p1,p2,p3 ) 
#endif

/* Check for the uninitialized values */
#define PGP_TOKEN_HANDLE_OK( handle ) \
	pgpAssert( (handle) != 0xcdcdcdcd && (handle) != 0xcccccccc && (handle) != (-1) );

#pragma pack(push, _pgpTokenKeyInfoPriv, 1)
typedef struct _pgpTokenKeyInfoPriv {
	PGPByte keyid[KEYIDLEN];

	PGPBoolean pgpData;	
	PGPUInt8 alg;		/* kPGPPublicKeyAlgorithm_RSA */

    PGPInt16 id_size;	/* CKA_ID, connecting related objects */

	CK_OBJECT_CLASS obj_class;	/* type of 'handle' */
	CK_OBJECT_HANDLE handle;/* corresponding PKCS11 object 
							(PGP data object or PKCS11 public key) */

    PGPByte id[ID_LEN_MAX];
} pgpTokenKeyInfoPriv;
#pragma pack(pop, _pgpTokenKeyInfoPriv)

typedef struct _pgpTokenCertInfoPriv {
	PGPByte keyid[KEYIDLEN];    
	CK_OBJECT_HANDLE handle;    /* X509 cert object */
} pgpTokenCertInfoPriv;


/****** INTERNAL FUNCTIONS ********/

/* Labels are likely to be visible to the user in viewers/browsers.
   It is safe to change them only here */
const static CK_CHAR application[] =    "PGP";
static const CK_CHAR labelPrefix[] =    "PGP Key Data 0x";

static PGPByte certLabelPrefix[] =      "PGP Cert. ";
											/* + user identity + */
static PGPByte certLabelSuffix[] =      " 0x";
											/* + keyID */

static CK_CHAR labelPub[] =             "PGP Public Key";
static CK_CHAR labelPubSub[] =          "PGP Public Subkey";

static CK_CHAR labelPriv[] =            "PGP Private Key";
static CK_CHAR labelPrivSub[] =         "PGP Private Subkey";

typedef PGPByte pgpPubKeyDataLabel[sizeof(labelPrefix)+2*KEYIDLEN];

/* Given KeyID, outputs string representation of it into 'out'
   Returns the number of bytes written
*/
static unsigned 
sKeyIDToString( const PGPByte *keyID, PGPByte out[2*KEYIDLEN], PGPBoolean compat ) 
{
    int i;
    unsigned off=0;

    if( out == NULL )
        return KEYIDLEN * ( compat ? 1 : 2 );

    for( i = compat ? KEYIDLEN/2 : 0; i<KEYIDLEN; ++i )
	{
		PGPByte c = (keyID[i] >> 4) & 0xf;
		out[off++] = (c > 9) ? ('A'+c-10) : ('0'+c);
		c = keyID[i] & 0xf;
		out[off++] = (c > 9) ? ('A'+c-10) : ('0'+c);
	}

    return off;
}

/* Create label for public key data blob */
static void sKeyIDToPublicLabel( const PGPByte *keyID, CK_ULONG *size, pgpPubKeyDataLabel label )
{
	CK_ULONG off;

	memcpy( label, labelPrefix, sizeof(labelPrefix)-1 );
	off = sizeof(labelPrefix) - 1;
    off += sKeyIDToString( keyID, label + off, FALSE );

    *size = off;
}

/* Create label for PKCS11 cert. Caller must free it.
   size doesn't include '\0' character (but string has it) */

static PGPByte *
sKeyIDToP11CertLabel( const PGPByte *keyID, 
                const PGPByte *userID, PGPSize userID_len, 
                CK_ULONG *size )
{
    PGPSize max_size = sizeof(certLabelPrefix)-1;
    PGPByte *out, *p;

    max_size += userID_len;
    max_size += sizeof(certLabelSuffix)-1;
    max_size += sKeyIDToString( keyID, NULL, TRUE );

    p = out = malloc( max_size+sizeof('\0') );
    if( out == NULL )
        return NULL;

	memcpy( p, certLabelPrefix, sizeof(certLabelPrefix)-1 );
    p += sizeof(certLabelPrefix)-1; 
    
    memcpy( p, userID, userID_len );
    p += userID_len;

    memcpy( p, certLabelSuffix, sizeof(certLabelSuffix)-1 );
    p += sizeof(certLabelSuffix)-1;
    
    p += sKeyIDToString( keyID, p, TRUE );

    *p = '\0';
    *size = max_size;

    return out;
}


/* 
	This is used to find PKCS11 objects using PKCS11 template. 
	templSize is the size of the templ in bytes
	(therefore, use sizeof(templ)). 

    If in_buffer==NULL, then this function will malloc the handle buffer
	and return it. Caller must free returned value in this case. 

	If the in_buffer is not NULL, then the function will fill this buffer
	and return the pointer to this buffer. 
 */
static CK_OBJECT_HANDLE *
sFindP11Objs( PGPToken *tptr, 
 			  const CK_ATTRIBUTE *searchTempl, int templSize, int *n, 
			  CK_OBJECT_HANDLE *in_buffer, int in_buffer_n)
{
	CK_RV rv;
	const sizeSearch = templSize  / sizeof(*searchTempl);
	int howmany;
	int n_handles = 2; /* average number of expected handles */
	int n_handles_used=0;
	void *to_free=NULL;

	CK_OBJECT_HANDLE *handles = NULL; 

	*n = 0;

	if (!tptr->have_session)
	{
		pgpDebugMsg( "sFindP11Objs called with no smartcard session" );
		return NULL;
	}

	if( in_buffer == NULL )  {
		to_free = handles = (CK_OBJECT_HANDLE*)calloc( sizeof(CK_OBJECT_HANDLE), n_handles );
		if( handles == NULL )
			return NULL;
	}

	rv = F->C_FindObjectsInit(tptr->session, (CK_ATTRIBUTE *)searchTempl, sizeSearch);
	if (rv != CKR_OK)
	{
		pgpDebugMsg( "C_FindObjectsInit failed" );
		free( to_free );
		return NULL;
	}

	if( in_buffer == NULL )  {	/* buffer is not specified */

		pgpAssert( handles != NULL );

		/* There is no way to know how many handles will be found in advance. 
		   So we use the trial method. */
		while(TRUE) {
			howmany = 0;
			rv = F->C_FindObjects(tptr->session, handles+n_handles_used, n_handles-n_handles_used, &howmany);
			if (rv != CKR_OK)  {
				PGP_TOKEN_TRACE( "C_FindObjects failed" );
				free( handles );
				return NULL;
			}
			n_handles_used += howmany;

			/* make sure we read all of them */
			if( n_handles > n_handles_used )  
				break;

			n_handles *= 2;
			to_free = handles = realloc( handles, sizeof(CK_OBJECT_HANDLE)*n_handles );
			if( to_free == NULL )  {
				n_handles_used = 0;
				break;
			}
		} 
		howmany = n_handles_used;
	}
	else  {		/* buffer is given */
		handles = in_buffer;

		rv = F->C_FindObjects(tptr->session, in_buffer, in_buffer_n, &howmany);
		if (rv != CKR_OK)
		{
			pgpDebugMsg( "C_FindObjects failed" );
			howmany = 0;
		}
	}

	/* Always finalize */
	rv = F->C_FindObjectsFinal(tptr->session);
	if (rv != CKR_OK)
	{
		pgpDebugMsg( "C_FindObjectsFinal failed" );
		free( to_free );
		return NULL;
	}

	if( howmany == 0 )  {
		free( to_free );
		PGP_TOKEN_TRACE( "sFindP11Objs call returns NULL" );
		return NULL;
	}

	PGP_TOKEN_TRACE1( "sFindP11Objs call returns with data: %d items", howmany );

	*n = howmany;
	return handles;
}

/* 
	Given PKCS11 object with CKA_ID attribute, 
	returns the handle to the related object, matching the 'templ' 
	of the 'size'.
	We assume that input object and the object to be found are 
	'connected' by CKA_ID.

	First row of the 'templ' must be the CKA_ID attribute. 
	Input object must have CKA_ID attribute.
	First matched object will be returned.
	output will have output->id and output->id_size initialized. 

    if templ consists of only CKA_ID, then output is the same as input with 
	resolved CKA_ID in 'id' field
 */
PGPBoolean static 
sObjToRelatedObj( PGPToken *tptr, 
			const pgpTokenKeyInfoPriv *input, 
			CK_ATTRIBUTE *templ, int templ_size, 
			pgpTokenKeyInfoPriv *output )  
{
	CK_RV rv;
	int howmany;

	const PGPBoolean isID = ( input->id_size > 0 );
	PGPByte *pID = (PGPByte *)( isID ? input->id : NULL );
	int size = input->id_size;

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

	pgpAssert( !isID || input->id[0] );
	pgpAssert( templ[0].type == CKA_ID );
	pgpAssert( templ_size >= sizeof(templ[0]) );

	if( !isID ) {	/* ID is not specified, PKCS11 handle must */
		CK_ATTRIBUTE pubTemplate[] =  {
			{ CKA_ID, NULL, 0 }
		};

		pgpAssert( size == 0 );
		pgpAssert( input->handle );
	
		rv = F->C_GetAttributeValue(tptr->session, input->handle, pubTemplate, 1);
		if (rv != CKR_OK) {
			pgpDebugMsg( "C_GetAttributeValue failed" );
			return FALSE;
		}
		
		pID = malloc( pubTemplate[0].ulValueLen );
		if( pID == NULL )
			return FALSE;

		size = pubTemplate[0].ulValueLen;
		pubTemplate[0].pValue = pID;
		
		rv = F->C_GetAttributeValue(tptr->session, input->handle, pubTemplate, 1);
		if (rv != CKR_OK) {
			free(pID);
			pgpDebugMsg( "C_GetAttributeValue failed" );
			return FALSE;
		}

		PGP_TOKEN_TRACE("sObjToRelatedObj: ID was not given");
	}
#if PGP_DEBUG
	else
		PGP_TOKEN_TRACE("sObjToRelatedObj: ID was given");
#endif


	/* Now we certainly know ID of the desired object */
	if( templ_size > sizeof(templ[0]) )	 {	/* see if we need to find anything */
		CK_OBJECT_HANDLE handle;

		templ[0].pValue = (void*)pID;
		templ[0].ulValueLen = size;

		if( sFindP11Objs( tptr, templ, templ_size, &howmany, &handle, 1 ) == NULL )
		{
			PGP_TOKEN_TRACE( "sObjToRelatedObj: related object not found" );
			if( !isID )
				free( pID );
			return FALSE;
		}
		pgpAssert( howmany == 1 );

		output->handle = handle;
		output->obj_class = CKO_PUBLIC_KEY;

		if( size > sizeof(output->id) )
			size = sizeof(output->id);

		/* Store ID */
		output->id_size = size;

⌨️ 快捷键说明

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