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

📄 pgppubkey.c

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

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

#include "pgpDebug.h"
#include "pgpErrors.h"
#include "pgpPubKey.h"
#include "pgpKeyMisc.h"
#include "pgpMem.h"

#if PGP_RSA
#include "pgpRSAKey.h"
#include "pgpMSRSAGlue.h"
#endif

#include "pgpElGKey.h"
#include "pgpDSAKey.h"
#if PGP_EC
#include "pgpECKey.h"
#endif
#include "pgpP11Key.h"
#include "pgpFixedKey.h"

#ifndef PGP_RSA
#error "PGP_RSA requires a value"
#endif

#ifndef PGP_RSA_KEYGEN
#error "PGP_RSA_KEYGEN requires a value"
#endif

/* Error code used within this module for RSA not available */
#define kPGPLocalError_RSANotAvailable	kPGPError_FeatureNotAvailable

struct PGPPkAlg
{
	PGPByte pkAlg;
	int use;
} ;

#if PGP_ENCRYPT_DISABLE && PGP_DECRYPT_DISABLE
#define LOCAL_ENCRYPT	0
#else
#define LOCAL_ENCRYPT	PGP_PKUSE_ENCRYPT
#endif

#if PGP_SIGN_DISABLE && PGP_VERIFY_DISABLE
#define LOCAL_SIGN		0
#else
#define LOCAL_SIGN		PGP_PKUSE_SIGN
#endif

#define LOCAL_SIGN_ENCRYPT (LOCAL_SIGN | LOCAL_ENCRYPT)

static PGPPkAlg const pgpKnownPkAlgs[] = {
#if PGP_RSA
	{ kPGPPublicKeyAlgorithm_RSA,     			LOCAL_SIGN_ENCRYPT },
	{ kPGPPublicKeyAlgorithm_RSASignOnly, 		LOCAL_SIGN },
	{ kPGPPublicKeyAlgorithm_RSAEncryptOnly, 	LOCAL_ENCRYPT },
#else	/* PGP_RSA */
	{ kPGPPublicKeyAlgorithm_RSA,     			0 },
	{ kPGPPublicKeyAlgorithm_RSASignOnly,		0 },
	{ kPGPPublicKeyAlgorithm_RSAEncryptOnly, 	0 },
#endif	/* PGP_RSA */
	{ kPGPPublicKeyAlgorithm_ElGamal, 			LOCAL_ENCRYPT },
	{ kPGPPublicKeyAlgorithm_DSA,     			LOCAL_SIGN },
#if PGP_EC
	{ kPGPPublicKeyAlgorithm_ECSign,	 		LOCAL_SIGN },
	{ kPGPPublicKeyAlgorithm_ECEncrypt,		 	LOCAL_ENCRYPT },
#else	/* PGP_EC */
	{ kPGPPublicKeyAlgorithm_ECSign,	 		0 },
	{ kPGPPublicKeyAlgorithm_ECEncrypt,		 	0 },
#endif	/* PGP_EC */
};


/* Error codes which permit signature checking to continue */
PGPBoolean
pgpIsKeyRelatedError( PGPError err )
{
	if (err >= kPGPError_KEY_MIN && err <= kPGPError_KEY_MAX)
		return TRUE;
	if (err == kPGPLocalError_RSANotAvailable)
		return TRUE;
	if (err == kPGPError_KeyUnusableForSignature)
		return TRUE;
	return FALSE;
}


/* Return whether an algorithm can sign, encrypt, or do both */
PGPPkAlg const *
pgpPkalgByNumber(PGPByte pkalg)
{
	unsigned i;

	pkalg = ALGMASK(pkalg);
	for (i = 0; i < sizeof(pgpKnownPkAlgs)/sizeof(*pgpKnownPkAlgs); i++) {
		if (pgpKnownPkAlgs[i].pkAlg == pkalg)
			return pgpKnownPkAlgs + i;
	}
	return NULL;
}

PGPUInt32
pgpKeyAlgUse(PGPPkAlg const *pkalg)
{
	if (!pkalg)
		return 0;		/* It's no use... */
#if PGP_RSA && PGP_USECAPIFORRSA
	if( pkalg->pkAlg == kPGPPublicKeyAlgorithm_RSA ||
	    pkalg->pkAlg == kPGPPublicKeyAlgorithm_RSASignOnly ||
	    pkalg->pkAlg == kPGPPublicKeyAlgorithm_RSAEncryptOnly ) {
		return pkalg->use & pgpCAPIuse();
	}
#endif
	return pkalg->use;
}

PGPPubKey *
pgpPubKeyFromBuf(
	PGPContextRef	context,
	PGPByte			pkAlg,
	PGPByte const *	p,
	PGPSize			len,
	PGPError *		error)
{
	PGPPubKey *pub;

	switch (ALGMASK(pkAlg)) {
	  case kPGPPublicKeyAlgorithm_RSA:
	  case kPGPPublicKeyAlgorithm_RSASignOnly:
	  case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
#if PGP_RSA
		pub = rsaPubFromBuf( context, p, len, error);
		if (pub)
			pub->pkAlg = pkAlg;
#else	/* PGP_RSA */
		(void) p;
		(void) len;
		pub = NULL;
		*error = kPGPLocalError_RSANotAvailable;
#endif	/* PGP_RSA */
		return pub;
	  case kPGPPublicKeyAlgorithm_ElGamal:
	  	pub = elgPubFromBuf( context, p, len, error);
		if (pub)
			pub->pkAlg = pkAlg;
		return pub;
	  case kPGPPublicKeyAlgorithm_DSA:
	  	pub = dsaPubFromBuf( context, p, len, error);
		if (pub)
			pub->pkAlg = pkAlg;
		return pub;
	  case kPGPPublicKeyAlgorithm_ECSign:
	  case kPGPPublicKeyAlgorithm_ECEncrypt:
#if PGP_EC
		pub = ecPubFromBuf( context, p, len, error);
		if (pub)
			pub->pkAlg = pkAlg;
#else	/* PGP_EC */
		(void) p;
		(void) len;
		pub = NULL;
		*error = kPGPError_UnknownPublicKeyAlgorithm;
#endif	/* PGP_EC */
		return pub;
	  default:
		*error = kPGPError_UnknownPublicKeyAlgorithm;
		return 0;
	}
	
}

PGPSecKey *
pgpSecKeyFromBuf(
	PGPContextRef	context,
	PGPByte			pkAlg,
	PGPByte const *	p,
	PGPSize			len,
	PGPBoolean		v3,
	void *			tokenobj,
	PGPError *		error)
{
	PGPSecKey *sec;

	/* Handle token objects */
	if( IsntNull( tokenobj ) )
	{
		sec = p11SecFromBuf( context, p, len, v3, tokenobj, error );
		if( sec )
		{
			sec->pkAlg = pkAlg;
			return sec;
		}
	}

	switch(ALGMASK(pkAlg)) {
	  case kPGPPublicKeyAlgorithm_RSA:
	  case kPGPPublicKeyAlgorithm_RSASignOnly:
	  case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
#if PGP_RSA
		sec = rsaSecFromBuf( context, p, len, v3, error);
		if (sec)
			sec->pkAlg = pkAlg;
#else	/* PGP_RSA */
		(void) p;

		(void) len;
		(void) v3;
		sec = NULL;
		*error = kPGPLocalError_RSANotAvailable;
#endif	/* PGP_RSA */
		return sec;
	  case kPGPPublicKeyAlgorithm_ElGamal:
		sec = elgSecFromBuf( context, p, len, error);
		if (sec)
			sec->pkAlg = pkAlg;
		return sec;
	  case kPGPPublicKeyAlgorithm_DSA:
		sec = dsaSecFromBuf( context, p, len, error);
		if (sec)
			sec->pkAlg = pkAlg;
		return sec;
	  case kPGPPublicKeyAlgorithm_ECSign:
	  case kPGPPublicKeyAlgorithm_ECEncrypt:
#if PGP_EC
		sec = ecSecFromBuf( context, p, len, error);
		if (sec)
			sec->pkAlg = pkAlg;
#else	/* PGP_EC */
		(void) p;

		(void) len;
		(void) v3;
		sec = NULL;
		*error = kPGPError_UnknownPublicKeyAlgorithm;
#endif	/* PGP_EC */
		return sec;
	  default:
		*error = kPGPError_UnknownPublicKeyAlgorithm;
		return 0;
	}
}

/*
 * Scan a buffer and return the size of the part which corresponds to
 * a public key.  This is intended to be "lightweight" and not require
 * the overhead of instantiating a PGPPubKey.
 *
 * This rturns 0 if the size is unknown.
 */
PGPSize
pgpPubKeyPrefixSize(PGPByte pkAlg, PGPByte const *p, PGPSize len)
{
	switch(ALGMASK(pkAlg)) {
	case kPGPPublicKeyAlgorithm_RSA:
	case kPGPPublicKeyAlgorithm_RSASignOnly:
	case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
#if PGP_RSA
		  return rsaPubKeyPrefixSize(p, len);
#else
		  /* We know it is 2 MPI values, just parse past those */
		  return pgpBnParse(p, len, 2, NULL, NULL);
#endif
	case kPGPPublicKeyAlgorithm_ElGamal:
		  return elgPubKeyPrefixSize(p, len);
	case kPGPPublicKeyAlgorithm_DSA:
		  return dsaPubKeyPrefixSize(p, len);
	case kPGPPublicKeyAlgorithm_ECSign:
	case kPGPPublicKeyAlgorithm_ECEncrypt:
#if PGP_EC
		  return ecPubKeyPrefixSize(p, len);
#else
		  return 0;
#endif
	default:
		return 0;
	}
}

/*
 * The "progress" function is called periodically during key
 * generation to indicate that *something* is happening.
 * The "int c" gives a bit of indication as to *what* is
 * happening.  In fact, this is just the character that text-mode
 * PGP prints!  It will do as well as any other sort of enum
 * and makes life simple.
 *
 * The meaning of the character is somewhat type-dependent, but
 * the convention so far is:
 * '.' - Failed pseudoprimality test
 * '/' - Redoing initial setup work
 * '-' - Passed pseudoprimality test, further work needed
 * '+' - Passed pseudoprimality test, further work needed
 * '*' - Passed pseudoprimality test - almost done!
 * ' ' - Completed part of key generation, on to next phase.
 *       (Sorry, no way to know how many phases there are...)
 */

PGPSecKey *
pgpSecKeyGenerate(
	PGPContextRef	context,
	PGPPkAlg const *alg, unsigned bits,
	PGPBoolean fastgen, PGPBoolean v3,
	PGPRandomContext const *rc,
	int (*progress)(void *arg, int c), void *arg,
	void *tokenobj,
	PGPByte const *passphrase, PGPSize passphraseLength,
	PGPBoolean genMaster, PGPError *error)
{
	PGPSecKey *sec;
	PGPByte pkAlg;
 
    (void) v3;

	pgpAssert (alg);
	pkAlg = alg->pkAlg;

	/* Handle token objects */
	if( IsntNull( tokenobj ) )
	{
		sec = p11SecGenerate( context, pkAlg, bits, fastgen, v3, progress,
							  arg, tokenobj, passphrase, passphraseLength,
							  genMaster, error );
		if( sec )
		{
			sec->pkAlg = pkAlg;
		}
		return sec;
	}

	switch(ALGMASK(pkAlg)) {
	  case kPGPPublicKeyAlgorithm_RSA:
	  case kPGPPublicKeyAlgorithm_RSASignOnly:
	  case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
#if PGP_RSA && PGP_RSA_KEYGEN
		/* Use V3 for plain RSA keys, V4 for sign/encrypt versions */
		sec = rsaSecGenerate( context, bits, fastgen, v3,
					rc, progress, arg, error);
		if (sec)
			sec->pkAlg = pkAlg;
		return sec;
#else
		*error = kPGPLocalError_RSANotAvailable;
		return NULL;
#endif
	  case kPGPPublicKeyAlgorithm_ElGamal:
		sec = elgSecGenerate(context, bits, fastgen, rc, progress, arg, error);
		if (sec)
			sec->pkAlg = pkAlg;
		return sec;
	  case kPGPPublicKeyAlgorithm_DSA:
		sec = dsaSecGenerate(context, bits, fastgen, rc, progress, arg, error);
		if (sec)
			sec->pkAlg = pkAlg;
		return sec;
	  case kPGPPublicKeyAlgorithm_ECSign:
	  case kPGPPublicKeyAlgorithm_ECEncrypt:
#if PGP_EC
		sec = ecSecGenerate( context, bits, fastgen,
					rc, progress, arg, error);
		if (sec)
			sec->pkAlg = pkAlg;
		return sec;
#else
		*error = kPGPError_UnknownPublicKeyAlgorithm;
		return NULL;
#endif
	  default:
		*error = kPGPError_UnknownPublicKeyAlgorithm;
		return 0;
	}
}

/*
 * Return the amount of entropy needed to generate this key.  Entropy
 * is a security parameter, controlling the amount of unpredictability
 * needed in the key.  We have to be sure to return a value at least
 * as big as the actual depletion of the randpool which the keygen
 * creates.  For simplicity and predictability, we return the
 * non-fastgen values throughout, even though they are a bit larger
 * for DSA & ELG keys.  (The +128 is for the secret key encryption IV
 * and salt when the secret key is encrypted with the passphrase.)
 */
unsigned
pgpSecKeyEntropy(PGPPkAlg const *pkAlg, unsigned bits, PGPBoolean fastgen,
	PGPBoolean v3, void *tokenobj)
{
	unsigned xbits;

	if( IsntNull(tokenobj) )
	{
		return 0;
	}

	switch (ALGMASK(pkAlg->pkAlg)) {
	  case kPGPPublicKeyAlgorithm_RSA:
	  case kPGPPublicKeyAlgorithm_RSASignOnly:
	  case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
		  if( v3 )
		  {
			  /* In fastgen, use an estimate of the strength of the key. */
			  /* Note that the dlog estimate gives twice what we need */
			  if (fastgen) {
				  return pgpMax (384,
								 pgpDiscreteLogExponentBits (bits));
			  } else {
				  return bits + 128;
			  }
		  } else {
			  /*
			   * Need to return the exact number consumed by the
			   * algorithm here, since we will generate two keys.  This is
			   * more than the effective strength of the key, which is
			   * the estimate used for RSA above.
			   */
			  return bits + 128;
		  }
	  case kPGPPublicKeyAlgorithm_ElGamal:
		  xbits = pgpDiscreteLogExponentBits(bits)*3/2 + 128;
		  /* Always return fastgen value
		   * if (!fastgen || !pgpElGfixed (bits, NULL, NULL, NULL, NULL))
		   */
			  xbits += ELGDUMMYBITS;
		  return xbits;
	  case kPGPPublicKeyAlgorithm_DSA:
		  /* We make bits a multiple of 64, rounding up, in keygen */
		  bits = 64 * ((bits + 63) / 64);

		  /*
		   * Count the ~160 bits each needed to generate the self signature
		   * on the key's userid, and on the subkey, in addition to the
		   * "q bits" secret exponent.  That is why the 2* below.
		   */
		  xbits = 2*((bits<=1024)?160:pgpDiscreteLogExponentBits(bits))
			  	+ ((bits<=1024)?160:pgpDiscreteLogQBits(bits)) + 128;
		  /* Always return fastgen value
		   * if (!fastgen || !pgpDSAfixed (bits, NULL, NULL, NULL, NULL))
		   */
			  xbits += DSADUMMYBITS;
		  return xbits;
	  case kPGPPublicKeyAlgorithm_ECSign:
	  case kPGPPublicKeyAlgorithm_ECEncrypt:
		  /*
		   * Count the ~160 bits each needed to generate the self signature
		   * on the key's userid, and on the subkey, in addition to the
		   * "q bits" secret exponent.  That is why the 2* below.
		   */
		  return 2*bits;
	}
	pgpAssert (0);
	return 0;
}

⌨️ 快捷键说明

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