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

📄 pgpp11key.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 4 页
字号:
static PGPError
p11ConvertPassphrase(PGPSecKey *seckey, PGPEnv const *env,
	  char const *phrase, PGPSize plen, PGPByte *outbuf)
{
	PGPByte mask = 0;

	(void) env;
	(void) seckey;

	plen = pgpMin( plen, PASSBUFFERSIZE - 1 - sizeof(PGPUInt32) );

	*(PGPUInt32 *)outbuf = PASSBUFMAGIC;
	outbuf += sizeof(PGPUInt32);
	*outbuf++ = (PGPByte) plen;
	while( plen-- )
		*outbuf++ = (PGPByte)*phrase++ ^ (mask+=PASSBUFMASK);
	return kPGPError_NoErr;
}


/*
 * Try to unlock the secret key wih the given passphrase.  Returns >0
 * if it was the correct passphrase. =0 if it was not, and <0 on error.
 * Does not alter the key even if it's the wrong passphrase and already
 * unlocked.  A NULL passphrae will work if the key is unencrypted.
 */

static int
p11Unlock(PGPSecKey *seckey,
	  char const *phrase, PGPSize plen, PGPBoolean hashedPhrase)
{
	P11Sec *sec = (P11Sec *)seckey->priv;
	char passbuf[PASSBUFFERSIZE];
	int rslt;

	if( pgpFIPSModeEnabled() )
	{
		/* FIPS does not allow using keys with NULL passphrases */
		if( IsNull( phrase ) || plen == 0 )
			return( 0 );
	}
	
	if( hashedPhrase )
	{
		if( IsPGPError( sRecoverHashedPhrase( (const unsigned char *) phrase, plen, passbuf, &plen )))
			return 0;
		phrase = passbuf;
	}

	rslt = pgpTokenObjAuth( sec->tok, phrase, plen );
	if( rslt != 0 )
		return 0;		/* Failure */

	sec->locked = 0;
	return 1;
}

/*
 * Relock the key.
 */
static void
p11Lock(PGPSecKey *seckey)
{
	P11Sec *sec = (P11Sec *)seckey->priv;

	(void)pgpTokenObjDeAuth( sec->tok );
	sec->locked = 1;
}

static PGPSize
p11SecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format);


/*
 * Try to decrypt the given esk.  If the key is locked, try the given
 * passphrase.  It may or may not leave the key unlocked in such a case.
 * (Some hardware implementations may insist on a password per usage.)
 */
static int
p11Decrypt(PGPSecKey *seckey, PGPByte const *esk, PGPSize esklen,
		   PGPByte *key, PGPSize *keylen,
		   char const *phrase, PGPSize plen,
		   PGPPublicKeyMessageFormat format)
{
#if PGP_DECRYPT_DISABLE /* [ */

	(void)seckey;
	(void)esk;
	(void)esklen;
	(void)key;
	(void)keylen;
	(void)phrase;
	(void)plen;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_DECRYPT_DISABLE */  /* ]  [ */

	P11Sec *sec = (P11Sec *)seckey->priv;
	BigNum bn;
	PGPInt32 i;
	PGPInt32 j;
	PGPUInt32 t;
	PGPUInt32 modbytes;
	PGPMemoryMgrRef		mgr	= NULL;

	mgr	= PGPPeekContextMemoryMgr( seckey->context );

	if (sec->locked) {
		i = p11Unlock(seckey, phrase, plen, FALSE);
		if (i <= 0)
			return i ? i : kPGPError_KeyIsLocked;
		pgpAssert(!sec->locked);
	}

	if (esklen < 2)
		return kPGPError_BadSessionKeySize;
	
	bnBegin(&bn, mgr, TRUE);
	modbytes = bnBytes( &sec->mod );
	i = pgpBnGetFormatted(&bn, esk, esklen, modbytes, format);
	if (i <= 0)
		return kPGPError_BadSessionKeySize;

	bnExtractBigBytes( &bn, key, 0, modbytes );
	bnEnd(&bn);

	i = pgpTokenObjDecrypt( sec->tok, (void *)seckey->keyID, key, modbytes,
							key, modbytes );
	if (i < 0)  {
		if( i== kPGPError_SmartCardKeyNotFound ) {
			pgpKeyOffToken( seckey->keyDBObj );
			pgpSyncTokenToKeyDB( seckey->context, NULL, TRUE );
		}

		return i;
	}

	if ((PGPSize)i > modbytes || i < 3)
		return kPGPError_CorruptData;

	if (format == kPGPPublicKeyMessageFormat_PGP) {
		/* Check checksum (should this be here?) */
		t = 0;
		for (j = 1; j < i-2; j++)
			t += key[j];
		if (t != ((unsigned)key[i-2]<<8) + key[i-1])
			return kPGPError_CorruptData;
		pgpClearMemory(key+i-2, 2);

		/* The actual key */
		if (keylen)
			*keylen = (PGPSize)i-2;
	} else {
		/* The actual key */
		if (keylen)
			*keylen = (PGPSize)i;
	}

	return 0;

#endif /* PGP_DECRYPT_DISABLE */ /* ] */
}


/*
 * Return the size of the buffer needed, worst-case, for the decrypted
 * output.  This will be the size of the "key" parameter to p11Decrypt.
 * We use that as a temp buffer to hold the raw decrypted value so it must
 * be the same size as the modulus.
 */
static PGPSize
p11SecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
{
	P11Sec const *sec = (P11Sec *)seckey->priv;

	(void) format;

	return bnBytes(&sec->mod);
}

/* Return the largest possible PGPESK size for a given key */
static PGPSize
p11SecMaxesk(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
{
	P11Sec const *sec = (P11Sec *)seckey->priv;

	if (format == kPGPPublicKeyMessageFormat_PGP)
		return 2 + bnBytes(&sec->mod);
	else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
			 format == kPGPPublicKeyMessageFormat_X509  ||
			 format == kPGPPublicKeyMessageFormat_IKE)
		return bnBytes(&sec->mod);

	pgpAssert(0);
	return 0;
}

static PGPSize
p11SecMaxsig(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
{
	P11Sec const *sec = (P11Sec *)seckey->priv;

	if (format == kPGPPublicKeyMessageFormat_PGP)
		return 2 + bnBytes(&sec->mod);
	else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
			 format == kPGPPublicKeyMessageFormat_IKE ||
			 format == kPGPPublicKeyMessageFormat_X509)
		return bnBytes(&sec->mod);

	pgpAssert(0);
	return 0;
}

static int
p11Sign(PGPSecKey *seckey, PGPHashVTBL const *h, PGPByte const *hash,
	PGPByte *sig, PGPSize *siglen, PGPRandomContext const *rc,
	PGPPublicKeyMessageFormat format)
{
#if PGP_SIGN_DISABLE /* [ */

	(void)seckey;
	(void)h;
	(void)hash;
	(void)sig;
	(void)siglen;
	(void)rc;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else

	P11Sec *sec = (P11Sec *)seckey->priv;
	BigNum bn;
	int i;
	unsigned t;
	PGPUInt32 modbytes;
	PGPMemoryMgrRef		mgr	= NULL;
	
	mgr	= PGPPeekContextMemoryMgr( seckey->context );

	/* We don't need these arguments, although other algorithms may... */
	(void)rc;
	(void)format;

	if (sec->locked)
		return kPGPError_KeyIsLocked;

	bnBegin(&bn, mgr, TRUE);

	modbytes = bnBytes( &sec->mod );

	t = h->DERprefixsize;
	/* IKE does not put in hash OID */
	if (format == kPGPPublicKeyMessageFormat_IKE)
		t = 0;
	if (t+h->hashsize  > modbytes)
		return kPGPError_PublicKeyTooSmall;
	pgpClearMemory( sig,  t);
	memcpy(sig, h->DERprefix, t);
	memcpy(sig+t, hash, h->hashsize);
	t += h->hashsize;

	i = pgpTokenObjSign( sec->tok, seckey->keyID, sig, t, sig, modbytes );
	if (bnInsertBigBytes(&bn, sig, 0, modbytes) < 0)
		return kPGPError_OutOfMemory;
	pgpClearMemory( sig,  t);

	if (i >= 0) {
		t = 0;
		if (format == kPGPPublicKeyMessageFormat_X509) {
			/* Output unformatted, but with no leading zeros */
			format = kPGPPublicKeyMessageFormat_PKCS1;
			t += pgpBnPutFormatted(&bn, sig+t, bnBytes(&bn), format);
		} else {
			t += pgpBnPutFormatted(&bn, sig+t, bnBytes(&sec->mod), format);
		}
		if (siglen)
			*siglen = (PGPSize)t;
		i = 0;
	}
	else if( i== kPGPError_SmartCardKeyNotFound ) {
		pgpKeyOffToken( seckey->keyDBObj );
		pgpSyncTokenToKeyDB( seckey->context, NULL, TRUE );
	}
	bnEnd(&bn);
	return i;

#endif /* PGP_SIGN_DISABLE */ /* ] */
}


/*
 * Change passphrase on token.  Not implemented.
 */

static int
p11ChangeLock(PGPSecKey *seckey, PGPEnv const *env, 
	PGPRandomContext const *rc, char const *ophrase, PGPSize oplen,
	PGPBoolean oHashedPhrase, char const *phrase, PGPSize plen,
	PGPStringToKeyType s2ktype)
{
	P11Sec *sec = (P11Sec *)seckey->priv;
	char passbuf[PASSBUFFERSIZE];
	PGPError err;

	(void) env;
	(void) rc;
	(void) s2ktype;

	if( oHashedPhrase )
	{
		if( IsPGPError( err = sRecoverHashedPhrase( (const unsigned char *) ophrase, oplen,
													passbuf, &oplen ) ) )
			return err;
		ophrase = passbuf;
	}

	err = pgpTokenObjSetPIN( sec->tok, (char *)ophrase, oplen,
							 (char *)phrase, plen );
	
	pgpPurgePassphraseCache_back(seckey->context);

	return err;
}

static PGPSize
p11SecBufferLength(PGPSecKey const *seckey)
{
	(void) seckey;
	return 0;
}

static void
p11SecToBuffer(PGPSecKey const *seckey, PGPByte *buf)
{
	(void) seckey;
	(void) buf;
}


static int
p11SecParams(PGPSecKey const *seckey, BigNum *x1, BigNum *x2,
	BigNum *x3, BigNum *x4, BigNum *x5, BigNum *x6, BigNum *x7, BigNum *x8)
{
	(void) seckey;
	(void)x1;
	(void)x2;
	(void)x3;
	(void)x4;
	(void)x5;
	(void)x6;
	(void)x7;
	(void)x8;
	return kPGPError_PublicKeyUnimplemented;
}


/* Fill in secret key structure */
static void
p11FillSecKey(PGPSecKey *seckey, P11Sec *sec)
{
	seckey->priv	            = sec;
	seckey->destroy             = p11SecDestroy;
	seckey->pubkey              = p11Pubkey;
	seckey->islocked            = p11Islocked;
	seckey->lockingalgorithm    = p11LockingAlgorithm;
	seckey->s2ktype             = p11S2KType;
	seckey->convertpassphrase   = p11ConvertPassphrase;
	seckey->unlock              = p11Unlock;
	seckey->lock                = p11Lock;
	seckey->decrypt             = p11Decrypt;
	seckey->maxdecrypted        = p11SecMaxdecrypted;
	seckey->maxsig              = p11SecMaxsig;
	seckey->maxesk              = p11SecMaxesk;
	seckey->sign                = p11Sign;
	seckey->changeLock          = p11ChangeLock;
	seckey->bufferLength        = p11SecBufferLength;
	seckey->toBuffer            = p11SecToBuffer;
	seckey->secparams			= p11SecParams;
	seckey->setkeyid			= p11SecSetKeyID;
}


/* Create a new PGPSecKey object.

 */
PGPSecKey *
p11SecFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	PGPSize			size,
	PGPBoolean		v3,
	void *			tok,
	PGPError *		error)
{
	PGPSecKey *seckey;
	P11Sec *sec;
	PGPError	err	= kPGPError_OutOfMemory;
	PGPMemoryMgrRef		mgr	= PGPPeekContextMemoryMgr( context );
	PGPByte *cryptk;

	(void) v3;

	bnInit();

	/* Holds public part */
	cryptk = (PGPByte *)pgpContextMemAlloc(context,
		size, kPGPMemoryMgrFlags_Clear);
	if (cryptk) {
		sec = (P11Sec *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
		if (sec) {
			pgpClearMemory( sec, sizeof(*sec) );
			sec->context	= context;
			seckey = (PGPSecKey *) pgpContextMemAlloc(context,
						sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
			if (seckey) {
				PGPUInt32 v;

				seckey->context	= context;
				seckey->token	= TRUE;
				pgpCopyMemory( buf, cryptk, size );
				sec->cryptkey = cryptk;
				sec->cklen = size;

				bnBegin(&sec->mod, mgr, FALSE);
				sec->locked = 1;
				seckey->priv = sec;

				/* Hold pointer to token object */
				sec->tok = tok;

				/* Parse buf to get modulus */
				if (size < 5) {
					*error = kPGPError_KeyPacketTruncated;
					return NULL;
				}
				v = ((unsigned)buf[0] << 8) + buf[1];
				v = (v+7)/8;
				if (size < 5+v) {
					*error = kPGPError_KeyPacketTruncated;
					return NULL;
				}
				if (bnInsertBigBytes(&sec->mod, buf+2, 0, v) < 0) {
					*error = kPGPError_OutOfMemory;
				}

				p11FillSecKey(seckey, sec);
				*error = kPGPError_NoErr;
				return seckey;	/* Success! */
			}
			/* Error, clean up and exit */
			PGPFreeData( sec );			/* Wipes as it frees */
		}
	}
	*error = err;
	return NULL;
}


PGPSecKey *
p11SecGenerate(
	PGPContextRef context, PGPByte pkalg,
	unsigned bits, PGPBoolean fastgen, PGPBoolean v3,
	int progress(void *arg, int c), void *arg,
	void *tokptr, PGPByte const *passphrase, PGPSize passphraseLength,
	PGPBoolean genMaster, PGPError *error)
{
#if PGP_WIN32
	PGPSecKey *seckey;
	PGPMemoryMgrRef mgr;
	PGPToken *tok = tokptr;
	PGPByte tmpkeyid[8];
	PGPUInt32 modlen;
	PGPUInt32 pubexplen;
	PGPUInt32 pubbuflen;
	PGPUInt32 off;
	PGPByte *modbuf = NULL;
	PGPByte *pubbuf = NULL;
	PGPByte *pubexpbuf = NULL;
	PGPError err = kPGPError_NoErr;
	BigNum mod, exp;

	pgpAssert( IsntNull( tok ) );

	/* Unlock token */
	err = pgpTokenObjAuth( tok, passphrase, passphraseLength );
	if( err != 0 )
	{
		*error = kPGPError_BadPassphrase;
		return NULL;
	}

	pgpFillMemory( tmpkeyid, 8, 0x55 );	/* Temporary keyid value */

	mgr	= PGPPeekContextMemoryMgr( context );
	bnBegin( &mod, mgr, FALSE );
	bnBegin( &exp, mgr, FALSE );

	modlen = (bits+7)/8;
	modbuf = PGPNewData( mgr, modlen, 0 );
	pubexpbuf = PGPNewData( mgr, modlen, 0 );

	if (progress && IsPGPError( err = progress(arg, '.') ) )
		goto error;

	err = pgpTokenObjKeygen(tok, tmpkeyid, bits, genMaster, modbuf, pubexpbuf, &pubexplen);

⌨️ 快捷键说明

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