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

📄 pgpmsrsaglue.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * pgpMSRSAGlue.c - Interface to Microsoft CryptoAPI for RSA support
 *
 * This is an alternative to pgpRSAGlue.c, and should be used if that
 * module cannot be used for legal reasons.  It is only usable on
 * platforms which include Microsoft CAPI support.
 *
 * This code only accepts PKCS-style padding.  Very old versions of PGP
 * used a different padding style, which will not be compatible with
 * this module.
 *
 * $Id: pgpMSRSAGlue.c,v 1.11 1999/04/07 23:06:10 cpeterson Exp $
 */
 
#include "pgpSDKBuildFlags.h"
/*

 * This entire source file is under the control of the following conditional:
 */

#if PGP_USECAPIFORRSA	/* [ */


#include "pgpConfig.h"

#include "pgpDebug.h"
#include "pgpPubKey.h"
#include "pgpRSAGlue.h"
#include "pgpKeyMisc.h"
#include "bn.h"
#include "pgpErrors.h"
#include "pgpRandomX9_17.h"
#include "pgpMem.h"
#include "pgpHashPriv.h"
#include "pgpMSRSAGlue.h"

/* Early versions of wincrypt.h are missing these */
#ifndef MS_ENH_PROV
#define MS_ENH_PROV_A       "Microsoft Enhanced Cryptographic Provider v1.0"
#define MS_ENH_PROV_W       L"Microsoft Enhanced Cryptographic Provider v1.0"
#ifdef UNICODE
#define MS_ENH_PROV         MS_ENH_PROV_W
#else
#define MS_ENH_PROV         MS_ENH_PROV_A
#endif
#endif /* MS_ENH_PROV */

#ifndef CALG_3DES
#define CALG_3DES 0x00006603
#endif /* CALG_3DES */


/* Shorthand for accessing CAPI externs */
#define ex pgp_CAPI_externs

/* Our key container name, chosen not to conflict with a user name */
#define PGPCONTAINER	"PGPreservedContainer"

/* Magic values for blob headers */
#define RSAPUBMAGIC		0x31415352
#define RSAPRIVMAGIC	0x32415352
#define BVERSION		2

/* Byte packing macros, little endian */
#define B4(val) (val)&0xff, ((val)>>8)&0xff, ((val)>>16)&0xff, ((val)>>24)&0xff
#define B2(val) (val)&0xff, ((val)>>8)&0xff

/* Round n up to be a multiple of r */
#define MULOF(n,r) ((((n)+(r)-1)/(r))*(r))


/* Blob definitions */


/* Public key blob header */
typedef struct _PUBLICKEYBLOBHDR
{
	BLOBHEADER      header;
	RSAPUBKEY       rsapubkey;
} PUBLICKEYBLOBHDR;
/* Followed by modulus, rsapubkey.bitlen bits long, little endian */

/* Note that this is the same as PUBLICKEYBLOBHDR, just what follows differs */
typedef struct _PRIVATEKEYBLOBHDR
{
	BLOBHEADER      header;
	RSAPUBKEY       rsapubkey;
} PRIVATEKEYBLOBHDR;
/* Followed by (all in little endian form, bitlen rounded up to mul of 64):
 *	modulus, rsapubkey.bitlen bits long,
 *	prime1, rsapubkey.bitlen/2 bits long,
 *  prime2, rsapubkey.bitlen/2 bits long, (prime1 > prime2)
 *  exponent1, rsapubkey.bitlen/2 bits long (privateExponent % (prime1-1))
 *  exponent2, rsapubkey.bitlen/2 bits long (privateExponent % (prime2-1))
 *	coefficient, rsapubkey.bitlen/2 bits long (inverse of prime2 mod prime1)
 *  privateExponent, rsapubkey.bitlen bits long
 */


typedef struct _SIMPLEBLOBHDR
{
	BLOBHEADER      header;
	ALG_ID          algid;		/* of pubkey which encrypts session key */
} SIMPLEBLOBHDR;
/* Followed by session key, encrypted in PKCS-1 format with a public key */


/* Cache loadability information */
static PGPBoolean sLoadabilityTested = FALSE;
static PGPUInt32 sCAPIuse = 0;
/* Cache library handles and entry point vectors */
static HINSTANCE hLibAdv;
static HINSTANCE hLibCry;
#if !PGP_USECAPIFORMD2
static
#endif
       CAPIEntries pgp_CAPI_externs;	/* May be used by MD2 CAPI code */

#define DUMMYBITS 384

/*
 * Dummy key, 384 bits, with public exponent = private exponent = 1
 * Used when we don't want CAPI to do anything with our data.
 */
static PGPByte dummyKeyBlob[] = {
	/* Blob header */
	PRIVATEKEYBLOB, BVERSION, 0, 0, B4(CALG_RSA_KEYX),
	/* RSAPUBKEY values */
	B4(RSAPRIVMAGIC), B4(DUMMYBITS), B4(1),

	/* Modulus */
	0xc9, 0xd7, 0x0e, 0x21, 0xbb, 0xe0, 0xb5, 0x7a,
	0x09, 0x3f, 0x64, 0x2d, 0xd7, 0xd0, 0x5c, 0xd6,
	0x3b, 0xb3, 0xed, 0x00, 0xe3, 0x2f, 0x53, 0xd9,
	0x26, 0xee, 0x47, 0x2f, 0x3e, 0x40, 0x5f, 0xc0,
	0xf3, 0xb4, 0x25, 0x55, 0xea, 0xcf, 0x0b, 0x8f,
	0x08, 0x28, 0x1a, 0xdd, 0x3b, 0x2a, 0x49, 0x8c,
	/* Prime1 */
	0xe7, 0xc0, 0xd7, 0x29, 0x28, 0x71, 0xe3, 0xc4,
	0x05, 0x8c, 0xee, 0x1b, 0x37, 0xf4, 0x81, 0xe6,
	0x5e, 0xb8, 0x4d, 0x38, 0xd3, 0x56, 0x80, 0xfa,
	/* Prime2 */
	0xcf, 0x9b, 0x02, 0x98, 0x55, 0x23, 0x09, 0xc6,
	0x44, 0x82, 0x69, 0x63, 0xae, 0x68, 0xe1, 0xd2,
	0x25, 0xfc, 0xe6, 0xe6, 0xc4, 0x7b, 0x5d, 0x8f,
	/* Exponent1 */
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	/* Exponent2 */
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	/* Coefficient */
	0x12, 0x12, 0xcd, 0x7f, 0x49, 0x92, 0xdf, 0x92,
	0x3e, 0x0c, 0xc6, 0x76, 0x8e, 0x6e, 0x72, 0xd7,
	0xe6, 0x94, 0xdf, 0xd8, 0xc5, 0x7c, 0x7f, 0x1e,
	/* Private exponent */
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};




/* Returns TRUE if we were able to find everything and can use CAPI */
static PGPBoolean
LoadCAPIEntryPoints ()
{
	PGPBoolean success = FALSE;

	if (!(ex.CryptAcquireContext = GetProcAddress (hLibAdv,
				"CryptAcquireContextA")) &&
		!(ex.CryptAcquireContext = GetProcAddress (hLibCry,
				"CryptAcquireContextA")))
		goto done;
	if (!(ex.CryptReleaseContext = GetProcAddress (hLibAdv,
				"CryptReleaseContext")) &&
		!(ex.CryptReleaseContext = GetProcAddress (hLibCry,
				"CryptReleaseContext")))
		goto done;
	if (!(ex.CryptImportKey = GetProcAddress (hLibAdv,
				"CryptImportKey")) &&
		!(ex.CryptImportKey = GetProcAddress (hLibCry,
				"CryptImportKey")))
		goto done;
	if (!(ex.CryptExportKey = GetProcAddress (hLibAdv,
				"CryptExportKey")) &&
		!(ex.CryptExportKey = GetProcAddress (hLibCry,
				"CryptExportKey")))
		goto done;
	if (!(ex.CryptDestroyKey = GetProcAddress (hLibAdv,
				"CryptDestroyKey")) &&
		!(ex.CryptDestroyKey = GetProcAddress (hLibCry,
				"CryptDestroyKey")))
		goto done;
	if (!(ex.CryptCreateHash = GetProcAddress (hLibAdv,
				"CryptCreateHash")) &&
		!(ex.CryptCreateHash = GetProcAddress (hLibCry,
				"CryptCreateHash")))
		goto done;
	if (!(ex.CryptHashData = GetProcAddress (hLibAdv,
				"CryptHashData")) &&
		!(ex.CryptHashData = GetProcAddress (hLibCry,
				"CryptHashData")))
		goto done;
	if (!(ex.CryptSetHashParam = GetProcAddress (hLibAdv,
				"CryptSetHashParam")) &&
		!(ex.CryptSetHashParam = GetProcAddress (hLibCry,
				"CryptSetHashParam")))
		goto done;
	if (!(ex.CryptDestroyHash = GetProcAddress (hLibAdv,
				"CryptDestroyHash")) &&
		!(ex.CryptDestroyHash = GetProcAddress (hLibCry,
				"CryptDestroyHash")))
		goto done;
	if (!(ex.CryptVerifySignature = GetProcAddress (hLibAdv,
				"CryptVerifySignatureA")) &&
		!(ex.CryptVerifySignature = GetProcAddress (hLibCry,
				"CryptVerifySignatureA")))
		goto done;
	if (!(ex.CryptSignHash = GetProcAddress (hLibAdv,
				"CryptSignHashA")) &&
		!(ex.CryptSignHash = GetProcAddress (hLibCry,
				"CryptSignHashA")))
		goto done;
	success = TRUE;

done:
	if (!success) {
		if (hLibAdv)
			FreeLibrary (hLibAdv);
		if (hLibCry)
			FreeLibrary (hLibCry);
	}
	return success;
}


/* Test what CAPI features are available */
/* The compiler seems to be storing above the stack frame */
/* Try turning off optimizer */
#pragma optimize ("", off)
PGPUInt32
pgpCAPIuse ()
{
	HCRYPTPROV hProv;
	PGPBoolean DEFLoadable, ENHLoadable;

	if (!sLoadabilityTested) {
		sLoadabilityTested = TRUE;
		sCAPIuse = 0;
		hLibAdv = LoadLibrary ("advapi32.dll");
		if (!hLibAdv)
			return 0;
		hLibCry = LoadLibrary ("crypt32.dll");
		if (!LoadCAPIEntryPoints ())
			return 0;
		/* See if DEF provider is available */
		DEFLoadable = ex.CryptAcquireContext (&hProv, NULL, MS_DEF_PROV,
							PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
		if (DEFLoadable)
			ex.CryptReleaseContext (hProv);
		ENHLoadable = ex.CryptAcquireContext (&hProv, NULL, MS_ENH_PROV,
							PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
		if (ENHLoadable)
			ex.CryptReleaseContext (hProv);
		sCAPIuse = (DEFLoadable ? PGP_PKUSE_SIGN : 0) |
				   (ENHLoadable ? PGP_PKUSE_ENCRYPT : 0);
	}
	return sCAPIuse;
}
/* Restore default optimizations */
#pragma optimize ("", on)


/*
 * This returns nonzero if the key is too big, returning the
 * maximum number of bits that the library can accept.
 * We will also use it to check for constraints on how CAPI works.
 * This may mean that we will return an error even when the key is
 * smaller than the max.
 */
#define MAXSIZE 4096
int
rsaKeyTooBig(RSApub const *pub, RSAsec const *sec)
{
	if (pub) {
		if (bnBits(&pub->n) > MAXSIZE)
			return MAXSIZE;

		if (bnBytes(&pub->e) > sizeof(DWORD))
			return MAXSIZE;
	}
	if (sec) {
		if (bnBits(&sec->n) > MAXSIZE)
			return MAXSIZE;

		if (bnBytes(&sec->e) > sizeof(DWORD))
			return MAXSIZE;
	}
	return 0; /* OK */
}

/* Tell the size needed for a PUBLICKEYBLOB from a RSApub */
static PGPSize
rpubk_size(RSApub const *pub)
{
	PGPUInt32 bits = MULOF(bnBits(&pub->n), 64);
	PGPUInt32 len = bits/8;

	return sizeof(PUBLICKEYBLOBHDR) + len;
}

/* Tell the size needed for a PRIVATEKEYBLOB from a RSAsec */
static PGPSize
rprivk_size(RSAsec const *sec)
{
	PGPUInt32 bits = MULOF(bnBits(&sec->n), 64);
	PGPUInt32 len = bits/8;

	return sizeof(PRIVATEKEYBLOBHDR) + (9*len)/2;
}

/* Tell the size needed for a SIMPLEKEYBLOB given encryption mod bits */
static PGPSize
rsesk_size(PGPUInt32 modbits)
{
	modbits = MULOF(modbits, 8);
	return sizeof(SIMPLEBLOBHDR) + modbits/8;
}


/* Initialize a PUBLICKEYBLOB pubkey structure from a RSApub. */
static void
rpubk_init(PUBLICKEYBLOBHDR *rpubk, RSApub const *pub)
{
	PGPUInt32 bits = MULOF(bnBits(&pub->n), 64);
	PGPUInt32 len = bits/8;
	PGPByte *bnbuf;

	pgpClearMemory(rpubk, sizeof (*rpubk) + len);

	rpubk->header.bType = PUBLICKEYBLOB;
	rpubk->header.bVersion = BVERSION;
	rpubk->header.aiKeyAlg = CALG_RSA_KEYX;

	rpubk->rsapubkey.magic = RSAPUBMAGIC;
	rpubk->rsapubkey.bitlen = MULOF(bnBits(&pub->n), 8);
	bnExtractLittleBytes(&pub->e, (PGPByte *)&rpubk->rsapubkey.pubexp, 0,
						 sizeof(rpubk->rsapubkey.pubexp));

	bnbuf = (PGPByte *)rpubk + sizeof(*rpubk);
	bnExtractLittleBytes(&pub->n, bnbuf, 0, len);
}


/* Initialize RSAREF privkey structure from a RSAsec. */
static void
rprivk_init(PRIVATEKEYBLOBHDR *rprivk, RSAsec const *sec,
	PGPMemoryMgrRef	mgr, PGPBoolean fSign)
{
	PGPUInt32 bits = MULOF(bnBits(&sec->n), 64);
	PGPUInt32 len = bits/8;
	BigNum dmodp, dmodq, tmp;
	PGPByte *bnbuf;

	pgpClearMemory(rprivk, sizeof (*rprivk) + (9*len)/2);

	/* Calculate d mod p-1 and d mod q-1 */
	bnBegin(&dmodp, mgr, TRUE);
	bnBegin(&dmodq, mgr, TRUE);
	bnBegin(&tmp, mgr, TRUE);
	bnCopy(&tmp, &sec->p);
	bnSubQ(&tmp, 1);
	bnMod(&dmodp, &sec->d, &tmp);
	bnCopy(&tmp, &sec->q);
	bnSubQ(&tmp, 1);
	bnMod(&dmodq, &sec->d, &tmp);

	/* Fill in structure */
	rprivk->header.bType = PRIVATEKEYBLOB;
	rprivk->header.bVersion = BVERSION;
	rprivk->header.aiKeyAlg = fSign ? CALG_RSA_SIGN : CALG_RSA_KEYX;

	rprivk->rsapubkey.magic = RSAPRIVMAGIC;
	rprivk->rsapubkey.bitlen = MULOF(bnBits(&sec->n), 8);
	bnExtractLittleBytes(&sec->e, (PGPByte *)&rprivk->rsapubkey.pubexp, 0,
						 sizeof(rprivk->rsapubkey.pubexp));

	bnbuf = (PGPByte *)rprivk + sizeof(*rprivk);
	bnExtractLittleBytes(&sec->n, bnbuf, 0, len);
	bnbuf += len;
	/* CAPI uses convention p > q, the opposite of ours */
	bnExtractLittleBytes(&sec->q, bnbuf, 0, len/2);
	bnbuf += len/2;
	bnExtractLittleBytes(&sec->p, bnbuf, 0, len/2);
	bnbuf += len/2;
	bnExtractLittleBytes(&dmodq, bnbuf, 0, len/2);
	bnbuf += len/2;
	bnExtractLittleBytes(&dmodp, bnbuf, 0, len/2);
	bnbuf += len/2;
	bnExtractLittleBytes(&sec->u, bnbuf, 0, len/2);
	bnbuf += len/2;
	bnExtractLittleBytes(&sec->d, bnbuf, 0, len);

	bnEnd(&dmodp);
	bnEnd(&dmodq);
	bnEnd(&tmp);
}


/*
 * Initialize a SIMPLEBLOB structure from a buffer, where the blob
 * will be decrypted with a public key of the specified size in bits
 * Note that rsesk is sensitive and should be allocated securely.
 */
static void
rsesk_initfrom_buf(SIMPLEBLOBHDR *rsesk, PGPByte const *in, unsigned len,
				   PGPUInt32 modbits, PGPMemoryMgrRef mgr,
				   PGPRandomContext const *rc)
{
	PGPUInt32 modlen;
	PGPByte *bnbuf;
	BigNum skbn;

	modbits = MULOF(modbits, 8);
	modlen = modbits / 8;

	pgpClearMemory(rsesk, sizeof (*rsesk) + modlen);

	rsesk->header.bType = SIMPLEBLOB;
	rsesk->header.bVersion = BVERSION;
	rsesk->header.aiKeyAlg = CALG_3DES;
	rsesk->algid = CALG_RSA_KEYX;

	bnbuf = (PGPByte *)rsesk + sizeof(*rsesk);

	bnBegin (&skbn, mgr, TRUE);
	pgpPKCSPack (&skbn, in, len, PKCS_PAD_ENCRYPTED, modlen, rc);
	bnExtractLittleBytes (&skbn, bnbuf, 0, modlen);

	bnEnd (&skbn);
}

/*
 * Initialize a SIMPLEBLOB structure from a buffer, where the blob
 * will be decrypted with a public key of the specified size in bits
 */
static void
rsesk_initfrom_bn(SIMPLEBLOBHDR *rsesk, BigNum *bn, PGPUInt32 modbits)
{
	PGPUInt32 modlen;
	PGPByte *bnbuf;

	modbits = MULOF(modbits, 8);
	modlen = modbits / 8;

	pgpClearMemory(rsesk, sizeof (*rsesk) + modlen);

	rsesk->header.bType = SIMPLEBLOB;
	rsesk->header.bVersion = BVERSION;
	rsesk->header.aiKeyAlg = CALG_3DES;
	rsesk->algid = CALG_RSA_KEYX;

	bnbuf = (PGPByte *)rsesk + sizeof(*rsesk);
	bnExtractLittleBytes (bn, bnbuf, 0, modlen);
}


/*
 * Encrypt a buffer holding a session key with an RSA public key
 */
int
rsaPublicEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
	RSApub const *pub, PGPRandomContext const *rc)

⌨️ 快捷键说明

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