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

📄 pgpp11key.c

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

	$Id: pgpP11Key.c,v 1.80 2002/08/06 20:11:04 dallen Exp $
____________________________________________________________________________*/
#include "pgpSDKBuildFlags.h"

/* PKCS-11 (Cryptoki) Interface */

#include "pgpConfig.h"
#include <string.h>
#include <stddef.h>

#include "pgpDebug.h"
#include "pgpKeyMisc.h"
#include "pgpP11Key.h"
#include "pgpTokenLib.h"
#include "bn.h"
#include "pgpCFBPriv.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpHashPriv.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "bnprime.h"
#include "pgpPubKey.h"
#include "pgpRandomX9_17.h"
#include "pgpStr2Key.h"
#include "pgpContext.h"
#include "pgpEnv.h"
#include "pgpKeyPriv.h"
#include "pgpX509Priv.h"
#include "pgpFIPSPriv.h"

#ifdef PGP_WIN32
#include "pgpPktByte.h"
#include "pgpEndianConversion.h"
#endif

/* Size of buffer to hold passphrase */
#define PASSBUFFERSIZE		80
/* Magic number at start of such buffers */
#define PASSBUFMAGIC	0x44201312
/* Mask to hide passphrase in cached buffers */
#define PASSBUFMASK		0x9D

/* A PGPSecKey's priv points to this */
/* This struct is always allocated using PGPNewSecureData */
typedef struct P11Sec
{
	PGPContextRef	context;
	
	PGPToken		*tok;
	int				locked;
	BigNum			mod;		/* RSA Modulus */
	PGPByte			*cryptkey;
	PGPSize			cklen;
	DEBUG_STRUCT_CONSTRUCTOR( P11secPlus )
} P11Sec ;


PGPByte sP11Module[255] = { '\0' };


#if PGP_WIN32
static PGPBoolean sHadTcl = FALSE;

/* PGPtcl library entry points */
static struct PGPtclEntries {
	PGPError (*pgpTokenInit) (void);
	PGPToken *(*pgpGetNthTokenObject) (PGPUInt32 n);
	PGPToken *(*pgpGetTokenObjectByPrivKeyID) (const PGPByte *keyID);
	PGPUInt32 (*pgpCountTokenObjects) (void);
	PGPError (*pgpAcquireAllTokens) (void);
	PGPError (*pgpReleaseAllTokens) (void);
    PGPError (*pgpSetP11DllName)(const PGPByte *name);
    PGPError ( *pgpFreeMem ) (void *p);
	PGPInt32 (*pgpGetTokenNum)(PGPToken *token);
	PGPError (*pgpSetCertToKeyID)( pgpTokenCertToKeyID f, void *param );
};

static struct PGPtclEntries F;
static inited = FALSE;
static HINSTANCE hTCL = NULL;
static sLoadTclTries = 0;
static int sCustomTcl = -1;

/* matches type pgpTokenCertToKeyID */
static PGPBoolean sCertToKeyID( 
	const PGPByte *cert, PGPSize size, PGPInputFormat obj_type, PGPByte id[8], PGPUInt32 *alg, 
	void *param )
{
	PGPKeyDBRef db=NULL;
	PGPContextRef context = (PGPContextRef)param;
	PGPBoolean ret = FALSE;

	pgpAssert( param != NULL );	
	pgpAssert( obj_type == kPGPInputFormat_PEMEncodedX509Cert );	/* programming errors */

	if( param == NULL )
		return FALSE;

	memset( id, 0, 8 );
	*alg = 0;

	pgpDecodeX509Cert( (PGPByte *)cert, size, context, NULL, &db );

	if( ! IsNull(db) )  {
		PGPKeyDBObjRef key =
			pgpFirstKeyInKeySet( PGPPeekKeyDBRootKeySet( db ) );
		PGPKeyInfo *kinfo = pgpKeyToKeyInfo( key );
		
		if( kinfo != NULL && kinfo->keyID != NULL )  {
			memcpy( id, kinfo->keyID, 8 );
			*alg = kinfo->pkalg;
			ret = TRUE;
		}

		PGPFreeKeyDB( db );
	}
	
	return ret;
}

/* Load our PGPtcl(P11) library dynamically */
static void
sLoadTCL()
{
	if( !inited && IsNull(hTCL) )
	{
        PGPBoolean is_generic = FALSE;

        if( sCustomTcl == -1 )  {   /* Try once to load custom TCL */
		    hTCL = LoadLibrary("PGPtcl");
            if( IsNull(hTCL) )   {
                sCustomTcl = 0;
                inited = FALSE;
            }
            else  {
#if PGP_DEBUG
				OutputDebugString("sLoadTCL: custom TCL loaded (PGPtcl.dll)\n");
#endif
                sCustomTcl = 1;
                inited = TRUE;
            }
        }

        if( ! inited ) {
            if( sP11Module[0] != '\0' )  {
				inited = TRUE;  /* Tried -- no matter what the result */
                hTCL = LoadLibrary("PGPtclP11");
                if( IsntNull(hTCL) )  
                    is_generic = TRUE;
            }

        }

		if( IsntNull( hTCL ) )
		{
            memset( &F, 0, sizeof(F) );

			F.pgpTokenInit = (void *)GetProcAddress( hTCL,
					"pgpTokenInit" );
			F.pgpGetNthTokenObject = (void *)GetProcAddress( hTCL,
					"pgpGetNthTokenObject" );
			F.pgpGetTokenObjectByPrivKeyID = (void *)GetProcAddress( hTCL,
					"pgpGetTokenObjectByPrivKeyID" );
			F.pgpCountTokenObjects = (void *)GetProcAddress( hTCL,
					"pgpCountTokenObjects" );
			F.pgpAcquireAllTokens = (void *)GetProcAddress( hTCL,
					"pgpAcquireAllTokens" );
			F.pgpReleaseAllTokens = (void *)GetProcAddress( hTCL,
					"pgpReleaseAllTokens" );
			F.pgpFreeMem = (void *)GetProcAddress( hTCL,
					"pgpFreeMem" );
			F.pgpGetTokenNum = (void *)GetProcAddress( hTCL,
					"pgpGetTokenNum" );
		    F.pgpSetCertToKeyID = (void *)GetProcAddress( hTCL,
					"pgpSetCertToKeyID" );
            if( is_generic )
			    F.pgpSetP11DllName = (void *)GetProcAddress( hTCL,
					"pgpSetP11DllName" );
			if( IsNull( F.pgpTokenInit )
				|| IsNull( F.pgpGetNthTokenObject )
				|| IsNull( F.pgpGetTokenObjectByPrivKeyID )
				|| IsNull( F.pgpCountTokenObjects )
				|| IsNull( F.pgpAcquireAllTokens ) 
                || IsNull( F.pgpReleaseAllTokens ) 
                || IsNull( F.pgpFreeMem ) 
				|| IsNull( F.pgpGetTokenNum )
                || ( is_generic && IsNull( F.pgpSetP11DllName )) )
			{
				/* Incompatible library version, pretend it didn't load */
				FreeLibrary(hTCL);
				hTCL = NULL;
				memset( &F, 0, sizeof(F) );
			} else {
                pgpAssert( !is_generic || sP11Module[0] != '\0' );
                if( is_generic && F.pgpSetP11DllName( sP11Module ) != kPGPError_NoErr )  {
#if PGP_DEBUG
					OutputDebugString("PGPtclP11.pgpSetP11DllName() failed\n");
#endif
					FreeLibrary(hTCL);
                    hTCL = NULL;
					memset( &F, 0, sizeof(F) );
				}

                if( hTCL && F.pgpTokenInit() != kPGPError_NoErr )  {
#if PGP_DEBUG
					OutputDebugString("PGPtclP11.pgpTokenInit() failed\n");
#endif
					FreeLibrary(hTCL);
                    hTCL = NULL;
					memset( &F, 0, sizeof(F) );

					if( sLoadTclTries < 5 )  {
						sLoadTclTries ++;
						inited=FALSE;	/* Give more tries */
					}
#if PGP_DEBUG
					else
						OutputDebugString("PGPtclP11.pgpTokenInit() failed. No more tries\n");
#endif

				}
			}
		}
	}
}
#endif /* PGP_WIN32 */

#if PGP_WIN32

/* 
	Create PGP Public Key Packet V3/V4 from the keystub, RSA modulus and 
	public exponent. 

    Input size in bytes.
	Caller must free the pkt_out.
*/
static PGPError 
sPgpPubKeyPktFromRsa( PGPContextRef context, 
        const PGPByte *mod_buf, PGPSize mod_size, 
        const PGPByte *exp_buf, PGPSize exp_size, 
        const pgpTokenPubKeyStub *keyStub, 
	    PGPByte **pkt_out, PGPSize *pkt_len_out )
{
#if PGP_WIN32
#pragma pack(push, cryptoki, 1)
#endif
	struct RsaPktHdr {
		PGPByte		header;					/* 0 offset */
		PGPUInt16	total_len;				/* 1 */
		PGPByte		ver;	     			/* 3 */
		PGPUInt32	time;	         		/* 4 */
		union {
			PGPUInt16	expiration;				/* 8 */
			PGPByte		alg_v4;					/* 8 */
		};
		PGPByte		alg_v3;					/* 10 */
											/* 11 */
	};
	struct RsaPktHdr *rsa_pkt_hdr;
#if PGP_WIN32
#pragma pack(pop, cryptoki)
#endif
	const v = keyStub->flags & 0xf;
	const struct_size = sizeof(struct RsaPktHdr) - ( v==PGPVERSION_3 ? 0 : 2/*no expiration*/ );

	int total_size; 
	PGPByte *pkt_out_temp;
	PGPByte *p;
	PGPUInt16 size;

	pgpAssert( mod_size < 0x10000 && exp_size < 0x10000 );
	pgpAssert( keyStub && (keyStub->flags & 0x80) == 0 ); /* It can be full key later */

	*pkt_out = NULL;
	*pkt_len_out = 0;

	while( *(PGPByte *)exp_buf == 0x00 && exp_size > 0 )  {
		exp_buf++;
		exp_size--;
	}

	total_size = mod_size+exp_size + struct_size + 2*sizeof(PGPUInt16)/*MPI length*/;

	pkt_out_temp = (PGPByte*)pgpContextMemAlloc( context, total_size, 0 );

	if( pkt_out_temp == NULL )   
		return kPGPError_OutOfMemory;

	pgpAssert( v == PGPVERSION_3 || v == PGPVERSION_4 );

	rsa_pkt_hdr = (struct RsaPktHdr *)pkt_out_temp;

	size = total_size-sizeof(rsa_pkt_hdr->header)-sizeof(rsa_pkt_hdr->total_len);

	rsa_pkt_hdr->header = PKTBYTE_BUILD( PKTBYTE_PUBKEY, 1/*two octet length*/ ); 
	PGPUInt16ToEndian(size, kPGPBigEndian, (PGPByte*)&(rsa_pkt_hdr->total_len)); 
	rsa_pkt_hdr->ver = 	v;
	rsa_pkt_hdr->time = keyStub->creationtime;
	if( v == PGPVERSION_3 )  {
		rsa_pkt_hdr->alg_v3 = kPGPPublicKeyAlgorithm_RSA;
		rsa_pkt_hdr->expiration = 0;	/*never*/
	}
	else
		rsa_pkt_hdr->alg_v4 = kPGPPublicKeyAlgorithm_RSA;

	p = pkt_out_temp + struct_size;

	size = mod_size * 8;	
	pgpAssert( *(PGPByte *)mod_buf & 0x80 ); 
	PGPUInt16ToEndian(size, kPGPBigEndian, p);	/* in bits */
	p += sizeof(PGPUInt16);

	pgpCopyMemory( mod_buf, p, mod_size );
	p += mod_size;

	size = exp_size * 8;
	{	/* Determine the actual bit size */
		int byte = *(PGPByte *)exp_buf; /* Highest byte */

		if( byte == 0 )  {
			PGPFreeData( pkt_out_temp );
			return kPGPError_CorruptData;
		}
		while( (byte & 0x80) == 0 )  {
			size --;
			byte <<= 1;
		}
	}
	PGPUInt16ToEndian(/*in*/size, kPGPBigEndian, /*out*/p);	/* in bits */
	p += sizeof(PGPUInt16);

	pgpCopyMemory( exp_buf, p, exp_size );

	*pkt_out = (PGPByte *)pkt_out_temp;
	*pkt_len_out = total_size;

	return kPGPError_NoErr;
}

#endif /* WIN32 */


#if PGP_WIN32

static PGPByte *
sPgpPubKeyPktFromDataInfo( PGPContextRef context, const pgpTokenDataInfo *di, PGPSize *size )  {
    const PGPByte *e = (PGPByte*)(di+1);
    const PGPByte *m = e + di->exp_size;
    PGPByte *out;

    sPgpPubKeyPktFromRsa( context, m, di->mod_size, e, di->exp_size, 
                          &(di->pubKeyStub), &out, size );

    return out;
}

#endif /* WIN32 */

/** Public key functions **/

/*
 * Not implemented
 */
PGPPubKey *
p11PubFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	PGPSize			size,
	PGPError *		error)
{
	(void) context;
	(void) buf;
	(void) size;
	(void) error;
	*error = kPGPError_PublicKeyUnimplemented;
	return NULL;
}



/** Secret key functions **/

static void
p11SecDestroy(PGPSecKey *seckey)
{
	P11Sec *sec = (P11Sec *)seckey->priv;
	PGPContextRef	context;

	pgpAssertAddrValid( seckey, PGPSecKey );
	context	= seckey->context;

	/* Make sure token is locked when we free it */
	(void)pgpTokenObjDeAuth( sec->tok );

	PGPFreeData( sec );			/* Wipes as it frees */
	pgpClearMemory( seckey,  sizeof(seckey));
	pgpContextMemFree( context, seckey);
}

/*
 * Generate a PGPPubKey from a PGPSecKey
 */
static PGPPubKey *
p11Pubkey(PGPSecKey const *seckey)
{
	P11Sec *sec = (P11Sec *)seckey->priv;
	PGPError error;

	return pgpPubKeyFromBuf( seckey->context, seckey->pkAlg,
							 sec->cryptkey, sec->cklen, &error );
}

/*
 * Set keyid
 */
static void
p11SecSetKeyID(PGPSecKey *seckey, PGPByte *keyid)
{
#if PGP_WIN32
	P11Sec *sec = (P11Sec *)seckey->priv;
	/* Change keyid on the token */
	pgpTokenObjEditKeyList( sec->tok, seckey->keyID, keyid );
#endif
	pgpCopyMemory(keyid, seckey->keyID, sizeof(seckey->keyID));
}

/*
 * Yes, there *is* a reason that this is a function and no a variable.
 * On a hardware device with an automatic timeout,
 * it actually might need to do some work to find out.
 */
static int
p11Islocked(PGPSecKey const *seckey)
{
	P11Sec const *sec = (P11Sec *)seckey->priv;

	return sec->locked;
}


/*
 * Return the algorithm and (symmetric) key size used for locking/unlocking
 * the secret key.
 * This is not possible with token keys, they are locked in hardware.
 * We return a buffer size so that we can fake the passphrase conversion
 */
static PGPError
p11LockingAlgorithm(
	PGPSecKey const *seckey,
	PGPCipherAlgorithm *pAlg,
	PGPSize *pAlgKeySize
	)
{
	(void) seckey;
	if( IsntNull( pAlg ) )
		*pAlg = kPGPCipherAlgorithm_None;
	if( IsntNull( pAlgKeySize ) )
		*pAlgKeySize = PASSBUFFERSIZE;
	return kPGPError_NoErr;
}


/*
 * Return the StringToKey type for unlocking the given key.  We use
 * kPGPStringToKey_Literal to flag a secret split unlocking buffer.
 * Returns kPGPStringToKey_Simple if key has no passphrase.
 */
static PGPError
p11S2KType(
	PGPSecKey const *seckey,
	PGPStringToKeyType *s2kType
	)
{
	(void) seckey;
	(void) s2kType;
	return kPGPError_PublicKeyUnimplemented;
}


/* Recover passphrase from hashed version */
static PGPError
sRecoverHashedPhrase( PGPByte const *hphrase, PGPSize hphraseLen,
	char *pphrase, PGPSize *pplen )
{
	PGPByte mask = 0;
	PGPSize plen;

	if( hphraseLen < sizeof(PGPUInt32)+1
		|| *(PGPUInt32 *)hphrase != PASSBUFMAGIC )
		return kPGPError_BadPassphrase;
	hphrase += sizeof( PGPUInt32 );
	*pplen = plen = (PGPSize)*hphrase++;
	while( plen-- )
		*pphrase++ = *hphrase++ ^ (mask+=PASSBUFMASK);
	return kPGPError_NoErr;
}

/*
 * Convert a passphrase into a s2k literal buffer for the key.
 * Returns error code.  Output buffer will be size of the *pAlgKeySize
 * parameter from pgpSecKeyLockingalgorithm.
 * We store passphrase, preceded by length, lightly masked
 */

⌨️ 快捷键说明

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