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

📄 pgprsakey.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*____________________________________________________________________________
	Copyright (C) 1997 Network Associates Inc. and affiliated companies.
	All rights reserved.

	$Id: pgpRSAKey.c,v 1.65 1999/04/22 00:37:43 hal Exp $
____________________________________________________________________________*/

#include "pgpSDKBuildFlags.h"

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

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

/* This entire module is dependent on RSA being enabled */
#if PGP_RSA

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

#include "pgpDebug.h"
#include "pgpKeyMisc.h"
#include "pgpRSAGlue.h"
#include "pgpRSAKey.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"



#define RSA_DEFAULT_EXPONENT	17

#define ASSERTRSA(alg) pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSA || \
			      (ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSAEncryptOnly || \
			      (ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSASignOnly)
#define ASSERTRSASIG(alg) \
	pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSA || \
	 (ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSASignOnly)
#define ASSERTRSAENC(alg) \
		pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSA || \
		(ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSAEncryptOnly)


/* A PGPSecKey's priv points to this, an RSAsec plus the encrypted form... */
/* This struct is always allocated using PGPNewSecureData */
typedef struct RSAsecPlus
{
	PGPContextRef	context;
	
	RSAsec			s;
	PGPByte *		cryptkey;
	size_t			ckalloc;
	size_t			cklen;
	int				locked;
	PGPBoolean		v3;	/* True if key is in a pre PGPVERSION_4 packet */
	DEBUG_STRUCT_CONSTRUCTOR( RSAsecPlus )
} RSAsecPlus ;

/** Public key functions **/

static void
rsaPubDestroy(PGPPubKey *pubkey)
{
	RSApub *pub = (RSApub *)pubkey->priv;
	PGPContextRef	context;

	pgpAssertAddrValid( pubkey, PGPPubKey );
	context	= pubkey->context;

	ASSERTRSA(pubkey->pkAlg);
	
	bnEnd(&pub->n);
	bnEnd(&pub->e);
	pgpClearMemory( pub,  sizeof(pub));
	pgpContextMemFree( context, pub);
	pgpClearMemory( pubkey,  sizeof(pubkey));
	pgpContextMemFree(context, pubkey);
}

/* Return the largest possible PGPESK size for a given key */
static size_t
rsaPubMaxesk(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
{
	RSApub const *pub = (RSApub *)pubkey->priv;

	ASSERTRSAENC(pubkey->pkAlg);
	if (format == kPGPPublicKeyMessageFormat_PGP)
		return 2 + bnBytes(&pub->n);
	else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
			 format == kPGPPublicKeyMessageFormat_X509  ||
			 format == kPGPPublicKeyMessageFormat_IKE)
		return bnBytes(&pub->n);

	pgpAssert(0);
	return 0;
}

/* Return the largest possible input size for rsaEncrypt */
static size_t
rsaPubMaxdecrypted(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
{
	RSApub const *pub = (RSApub *)pubkey->priv;

	(void) format;
	ASSERTRSAENC(pubkey->pkAlg);

	/* Minimum padding could be just 0 2 0 */
	return bnBytes(&pub->n) - 3;
}

/* Return the largest possible signature input to rsaVerify */
static size_t
rsaPubMaxsig(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
{
	RSApub const *pub = (RSApub *)pubkey->priv;

	ASSERTRSASIG(pubkey->pkAlg);

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

	pgpAssert(0);
	return 0;
}


/*
 * Given a buffer of at least "maxesk" bytes, make an PGPESK
 * into it and return the size of the PGPESK, or <0.
 */
static int
rsaEncrypt(PGPPubKey const *pubkey, PGPByte const *key,
           size_t keylen, PGPByte *esk, size_t *esklen,
           PGPRandomContext const *rc, PGPPublicKeyMessageFormat format)
{
#if PGP_ENCRYPT_DISABLE /* [ */

	(void)pubkey;
	(void)key;
	(void)keylen;
	(void)esk;
	(void)esklen;
	(void)rc;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_ENCRYPT_DISABLE */  /* ]  [ */

	RSApub const *pub = (RSApub *)pubkey->priv;
	BigNum bn;
	unsigned t;
	int i;
	PGPMemoryMgrRef		mgr	= NULL;

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

	mgr	= PGPGetContextMemoryMgr( pubkey->context );

	ASSERTRSAENC(pubkey->pkAlg);
	t = bnBits(&pub->n);
	if (t > 0xffff)
		return kPGPError_PublicKeyTooLarge;
	if (keylen > t)
		return kPGPError_PublicKeyTooSmall; /* data too big for pubkey */

	if( format == kPGPPublicKeyMessageFormat_PGP ) {
		/* Add checksum to key, place temporarily in esk buffer */
		t = 0;
		esk[0] = key[0];
		for (i = 1; i < (int)keylen; i++)
			t += esk[i] = key[i];
		esk[keylen] = (PGPByte)(t >> 8 & 255);
		esk[keylen+1] = (PGPByte)(t & 255);
		keylen += 2;
		key = esk;
	}

	bnBegin(&bn, mgr, TRUE);
	i = rsaPublicEncrypt(&bn, key, keylen, pub, rc);
	if (i < 0) {
		bnEnd(&bn);
		return i;
	}
	
	t = pgpBnPutFormatted(&bn, esk, bnBytes(&pub->n), format);
	bnEnd(&bn);

	if (esklen)
		*esklen = (size_t)t;
	return 0;

#endif /* PGP_ENCRYPT_DISABLE */ /* ] */
}


/*
 * Return 1 if (sig,siglen) is a valid MPI which signs
 * hash, of type h.  Check the DER-encoded prefix and the
 * hash itself.
 */
static int
rsaVerify(PGPPubKey const *pubkey, PGPByte const *sig,
	size_t siglen, PGPHashVTBL const *h, PGPByte const *hash,
	PGPPublicKeyMessageFormat format)
{
#if PGP_VERIFY_DISABLE /* [ */

	(void)pubkey;
	(void)sig;
	(void)siglen;
	(void)h;
	(void)hash;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_VERIFY_DISABLE */  /* ]  [ */

	RSApub const *pub = (RSApub *)pubkey->priv;
	BigNum bn;
	PGPByte buf[64];	/* largest hash size + DER prefix */
	int i;
	size_t off = 0;
	PGPMemoryMgrRef	mgr	= PGPGetContextMemoryMgr( pubkey->context );

	ASSERTRSASIG(pubkey->pkAlg);

	bnBegin(&bn, mgr, FALSE);
	if (format == kPGPPublicKeyMessageFormat_X509) {
		/* Unformatted data, taking up whole length of buffer */
		format = kPGPPublicKeyMessageFormat_PKCS1;
		i = pgpBnGetFormatted(&bn, sig+off, siglen-off, siglen-off, format);
	} else {
		i = pgpBnGetFormatted(&bn, sig+off, siglen-off, bnBytes(&pub->n),
							  format);
	}
	if (i <= 0)
		return kPGPError_BadSignatureSize;

#if PGP_USECAPIFORRSA
	i = rsaVerifyHashSignature(&bn, pub, h, hash);
#else
	i = rsaPublicDecrypt(buf, sizeof(buf), &bn, pub);

	if (i >= 0) {
		/* Check that the returned data is correct */
		unsigned t = h->DERprefixsize;
		/* IKE does not put in hash OID */
		if (format == kPGPPublicKeyMessageFormat_IKE)
			t = 0;
		i = (size_t)i <= sizeof(buf)
		    && (unsigned)i == h->hashsize + t
		    && memcmp(buf, h->DERprefix, t) == 0
		    && memcmp(buf+t, hash, h->hashsize) == 0;
	}
#endif
	bnEnd(&bn);
	pgpClearMemory( buf,  sizeof(buf));
	return i;

#endif /* PGP_VERIFY_DISABLE */ /* ] */
}


/*
 * Turn a PGPPubKey into the algorithm-specific parts of a public key.
 * A public key's RSA-specific part is:
 *
 *  0      2+i  MPI for modulus
 * 2+i     2+t  MPI for exponent
 * 4+i+t
 */
static size_t
rsaPubBufferLength(PGPPubKey const *pubkey)
{
	RSApub const *pub = (RSApub *)pubkey->priv;

	return 4 + bnBytes(&pub->n) + bnBytes(&pub->e);
}

static void
rsaPubToBuffer(PGPPubKey const *pubkey, PGPByte *buf)
{
	RSApub const *pub = (RSApub *)pubkey->priv;
	unsigned i, t;

	i = bnBits(&pub->n);
	pgpAssert(i <= 0xffff);
	buf[0] = (PGPByte)(i >> 8);
	buf[1] = (PGPByte)i;
	i = (i+7)/8;
	bnExtractBigBytes(&pub->n, buf+2, 0, i);
	t = bnBits(&pub->e);
	pgpAssert(t <= 0xffff);
	buf[2+i] = (PGPByte)(t >> 8);
	buf[3+i] = (PGPByte)t;
	t = (t+7)/8;
	bnExtractBigBytes(&pub->e, buf+4+i, 0, t);
}


/* A little helper function that's used twice */
static void
rsaFillPubkey(PGPPubKey *pubkey, RSApub *pub)
{
	pubkey->next	 = NULL;
	pubkey->pkAlg	 = kPGPPublicKeyAlgorithm_RSA;
	pubkey->priv	 = pub;
	pubkey->destroy  = rsaPubDestroy;
	pubkey->maxesk   = rsaPubMaxesk;
	pubkey->maxdecrypted   = rsaPubMaxdecrypted;
	pubkey->maxsig   = rsaPubMaxsig;
	pubkey->encrypt  = rsaEncrypt;
	pubkey->verify   = rsaVerify;
	pubkey->bufferLength  = rsaPubBufferLength;
	pubkey->toBuffer = rsaPubToBuffer;
}


/*
 * Turn the algorithm-specific parts of a public key into a PGPPubKey
 * structure.  A public key's RSA-specific part is:
 *
 *  0      2+i  MPI for modulus
 * 2+i     2+t  MPI for exponent
 * 4+i+t
 */
PGPPubKey *
rsaPubFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	size_t			size,
	PGPError *		error)
{
	PGPPubKey *pubkey;
	RSApub *pub;
	unsigned i, t;
	PGPError	err	= kPGPError_OutOfMemory;
	PGPMemoryMgrRef	mgr	= PGPGetContextMemoryMgr( context );

	bnInit();

	if (size < 4)
		return NULL;

	i = ((unsigned)buf[0] << 8) + buf[1];
	if (!i || buf[2] >> ((i-1) & 7) != 1) {
		*error = kPGPError_MalformedKeyModulus;
		return NULL;	/* Bad bit length */
	}
	i = (i+7)/8;
	if (size < 4+i) {
		*error = kPGPError_KeyPacketTruncated;
		return NULL;
	}
	if ((buf[1+i] & 1) == 0) {	/* Too small or even modulus */
		*error = kPGPError_RSAPublicModulusIsEven;
		return NULL;
	}
	t = ((unsigned)buf[2+i] << 8) + buf[3+i];
	if (!t || buf[4+i] >> ((t-1) & 7) != 1) {
		*error = kPGPError_MalformedKeyExponent;
		return NULL;	/* Bad bit length */
	}
	t = (t+7)/8;
	if (size < 4+i+t) {
		*error = kPGPError_KeyPacketTruncated;
		return NULL;
	}

	pub = (RSApub *)pgpContextMemAlloc( context,
		sizeof(*pub), kPGPMemoryMgrFlags_Clear );
	if (pub) {
		pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
			sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
		if (pubkey) {
			pubkey->context	= context;
			bnBegin(&pub->n, mgr, FALSE);
			bnBegin(&pub->e, mgr, FALSE);
			if (bnInsertBigBytes(&pub->n, buf+2, 0, i) >= 0
			    && bnInsertBigBytes(&pub->e, buf+4+i, 0, t) >= 0)
			{
				if (rsaKeyTooBig (pub, NULL) ||
					bnBits(&pub->n) > 2048 ) {
					err = kPGPError_KeyTooLarge;
				} else {
					rsaFillPubkey(pubkey, pub);
					*error = 0;
					return pubkey;
				}
			}
			/* Failed = clean up and return NULL */
			bnEnd(&pub->n);
			bnEnd(&pub->e);
			pgpContextMemFree( context, pubkey);
		}
		pgpContextMemFree( context, pub);
	}
	*error = err;
	return NULL;
}

/*
 * Return the size of the public portion of a key buffer.
 */
int
rsaPubKeyPrefixSize(PGPByte const *buf, size_t size)
{
	return pgpBnParse(buf, size, 2, NULL, NULL);
}



/** Secret key functions **/

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

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

	ASSERTRSA(seckey->pkAlg);
	bnEnd(&sec->s.n);
	bnEnd(&sec->s.e);
	bnEnd(&sec->s.d);
	bnEnd(&sec->s.p);
	bnEnd(&sec->s.q);
	bnEnd(&sec->s.u);
	pgpClearMemory(sec->cryptkey, sec->ckalloc);
	pgpContextMemFree( context, sec->cryptkey);
	PGPFreeData( sec );			/* Wipes as it frees */
	pgpClearMemory( seckey,  sizeof(seckey));
	pgpContextMemFree( context, seckey);
}

/*
 * Generate a PGPPubKey from a PGPSecKey
 */
static PGPPubKey *
rsaPubkey(PGPSecKey const *seckey)
{
	RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
	PGPPubKey *pubkey;
	RSApub *pub;
	PGPContextRef	context;
	PGPMemoryMgrRef		mgr	= NULL;

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

	ASSERTRSA(seckey->pkAlg);
	pub = (RSApub *)pgpContextMemAlloc( context, 
		sizeof(*pub), kPGPMemoryMgrFlags_Clear);
	if (pub) {
		pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
			sizeof(*pubkey), kPGPMemoryMgrFlags_Clear );
		if (pubkey) {
			pubkey->context	= seckey->context;
			
			bnBegin(&pub->n, mgr, FALSE);
			bnBegin(&pub->e, mgr, FALSE);
			if (bnCopy(&pub->n, &sec->s.n) >= 0
			    && bnCopy(&pub->e, &sec->s.e) >= 0)
			{
				rsaFillPubkey(pubkey, pub);
				pubkey->pkAlg = seckey->pkAlg;
				memcpy(pubkey->keyID, seckey->keyID,
				       sizeof(pubkey->keyID));
				return pubkey;
			}
			/* Failed = clean up and return NULL */
			bnEnd(&pub->n);
			bnEnd(&pub->e);
			pgpContextMemFree( context, pubkey);
		}
		pgpContextMemFree(context, pub);
	}
	return NULL;
}

/*
 * 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
rsaIslocked(PGPSecKey const *seckey)
{
	RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;

	ASSERTRSA(seckey->pkAlg);
	return sec->locked;
}


/*
 * Return the algorithm and (symmetric) key size used for locking/unlocking

⌨️ 快捷键说明

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