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

📄 pgptwofish.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 3 页
字号:
	if ((useAsm & 1) && (inputLen))
  #ifdef COMPILE_KEY
		if (key->keySig == VALID_SIG)
			return ((CipherProc *)(key->encryptFuncPtr))(cipher,key,input,inputLen,outBuffer);
  #else	
		return (*blockEncrypt_86)(cipher,key,input,inputLen,outBuffer);
  #endif
#endif
	/* make local copy of subkeys for speed */
	memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds));
	if (mode == MODE_CBC)
		BlockCopy(IV,cipher->iv32)
	else
		IV[0]=IV[1]=IV[2]=IV[3]=0;

	for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
		{
#ifdef DEBUG
		DebugDump(input,"\n",-1,0,0,0,1);
		if (cipher->mode == MODE_CBC)
			DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
#endif
#define	LoadBlockE(N)  x[N]=Bswap(((DWORD *)input)[N]) ^ sk[INPUT_WHITEN+N] ^ IV[N]
		LoadBlockE(0);	LoadBlockE(1);	LoadBlockE(2);	LoadBlockE(3);
		DebugDump(x,"",0,0,0,0,0);
#define	EncryptRound(K,R,id)	\
			t0	   = Fe32##id(x[K  ],0);					\
			t1	   = Fe32##id(x[K^1],3);					\
			x[K^3] = ROL(x[K^3],1);							\
			x[K^2]^= t0 +   t1 + sk[ROUND_SUBKEYS+2*(R)  ];	\
			x[K^3]^= t0 + 2*t1 + sk[ROUND_SUBKEYS+2*(R)+1];	\
			x[K^2] = ROR(x[K^2],1);							\
			DebugDump(x,"",rounds-(R),0,0,1,0);
#define		Encrypt2(R,id)	{ EncryptRound(0,R+1,id); EncryptRound(2,R,id); }

#if defined(ZERO_KEY)
		switch (key->keyLen)
			{
			case 128:
				for (i=rounds-2;i>=0;i-=2)
					Encrypt2(i,_128);
				break;
			case 192:
				for (i=rounds-2;i>=0;i-=2)
					Encrypt2(i,_192);
				break;
			case 256:
				for (i=rounds-2;i>=0;i-=2)
					Encrypt2(i,_256);
				break;
			}
#else
		Encrypt2(14,_);
		Encrypt2(12,_);
		Encrypt2(10,_);
		Encrypt2( 8,_);
		Encrypt2( 6,_);
		Encrypt2( 4,_);
		Encrypt2( 2,_);
		Encrypt2( 0,_);
#endif

		/* need to do (or undo, depending on your point of view) final swap */
#if LittleEndian
#define	StoreBlockE(N)	((DWORD *)outBuffer)[N]=x[N^2] ^ sk[OUTPUT_WHITEN+N]
#else
#define	StoreBlockE(N)	{ t0=x[N^2] ^ sk[OUTPUT_WHITEN+N]; ((DWORD *)outBuffer)[N]=Bswap(t0); }
#endif
		StoreBlockE(0);	StoreBlockE(1);	StoreBlockE(2);	StoreBlockE(3);
		if (mode == MODE_CBC)
			{
			IV[0]=Bswap(((DWORD *)outBuffer)[0]);
			IV[1]=Bswap(((DWORD *)outBuffer)[1]);
			IV[2]=Bswap(((DWORD *)outBuffer)[2]);
			IV[3]=Bswap(((DWORD *)outBuffer)[3]);
			}
#ifdef DEBUG
		DebugDump(outBuffer,"",rounds+1,0,0,0,1);
		if (cipher->mode == MODE_CBC)
			DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
#endif
		}

	if (mode == MODE_CBC)
		BlockCopy(cipher->iv32,IV);

	return inputLen;
}

/*
+*****************************************************************************
*
* Function Name:	blockDecrypt
*
* Function:			Decrypt block(s) of data using Twofish
*
* Arguments:		cipher		=	ptr to already initialized cipherInstance
*					key			=	ptr to already initialized keyInstance
*					input		=	ptr to data blocks to be decrypted
*					inputLen	=	# bits to encrypt (multiple of blockSize)
*					outBuffer	=	ptr to where to put decrypted blocks
*
* Return:			# bits ciphered (>= 0)
*					else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
*
* Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
*		 If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
*		 an error BAD_INPUT_LEN is returned.  In CFB1 mode, all block 
*		 sizes can be supported.
*
-****************************************************************************/
int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
				int inputLen, BYTE *outBuffer)
{
	int   i,n;						/* loop counters */
	DWORD x[BLOCK_SIZE/32];			/* block being encrypted */
	DWORD t0,t1;					/* temp variables */
	int	  rounds=key->numRounds;	/* number of rounds */
	BYTE  bit,ctBit,carry;			/* temps for CFB */
#if ALIGN32
	BYTE  dummyAlign = 0;			/* keep dword alignment on stack */
#endif
	/* make local copies of things for faster access */
	int	  mode = cipher->mode;
	DWORD sk[TOTAL_SUBKEYS];
	DWORD IV[BLOCK_SIZE/32];

	GetSboxKey;

#if ALIGN32
	(void) dummyAlign;
#endif

#if VALIDATE_PARMS
	if ((cipher == NULL) || (cipher->cipherSig != VALID_SIG))
		return BAD_CIPHER_STATE;
	if ((key == NULL) || (key->keySig != VALID_SIG))
		return BAD_KEY_INSTANCE;
	if ((rounds < 2) || (rounds > MAX_ROUNDS) || (rounds&1))
		return BAD_KEY_INSTANCE;
	if ((cipher->mode != MODE_CFB1) && (inputLen % BLOCK_SIZE))
		return BAD_INPUT_LEN;
  #if ALIGN32
	if ( (((int)cipher) & 3) || (((int)key      ) & 3) ||
		 (((int)input)  & 3) || (((int)outBuffer) & 3))
		return BAD_ALIGN32;
  #endif
#endif

	if (cipher->mode == MODE_CFB1)
		{	/* use blockEncrypt here to handle CFB, one block at a time */
		cipher->mode = MODE_ECB;	/* do encryption in ECB */
		for (n=0;n<inputLen;n++)
			{
			blockEncrypt(cipher,key,cipher->IV,BLOCK_SIZE,(BYTE *)x);
			bit	  = 0x80 >> (n & 7);
			ctBit = input[n/8] & bit;
			outBuffer[n/8] = (outBuffer[n/8] & ~ bit) |
							 (ctBit ^ ((((BYTE *) x)[0] & 0x80) >> (n&7)));
			carry = ctBit >> (7 - (n&7));
			for (i=BLOCK_SIZE/8-1;i>=0;i--)
				{
				bit = cipher->IV[i] >> 7;	/* save next "carry" from shift */
				cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
				carry = bit;
				}
			}
		cipher->mode = MODE_CFB1;	/* restore mode for next time */
		return inputLen;
		}

	/* here for ECB, CBC modes */
	if (key->direction != DIR_DECRYPT)
		ReverseRoundSubkeys(key,DIR_DECRYPT);	/* reverse the round subkey order */

#ifdef USE_ASM
	if ((useAsm & 2) && (inputLen))
  #ifdef COMPILE_KEY
		if (key->keySig == VALID_SIG)
			return ((CipherProc *)(key->decryptFuncPtr))(cipher,key,input,inputLen,outBuffer);
  #else	
		return (*blockDecrypt_86)(cipher,key,input,inputLen,outBuffer);
  #endif
#endif
	/* make local copy of subkeys for speed */
	memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds));
	if (mode == MODE_CBC)
		BlockCopy(IV,cipher->iv32)
	else
		IV[0]=IV[1]=IV[2]=IV[3]=0;

	for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
		{
		DebugDump(input,"\n",rounds+1,0,0,0,1);
#define LoadBlockD(N) x[N^2]=Bswap(((DWORD *)input)[N]) ^ sk[OUTPUT_WHITEN+N]
		LoadBlockD(0);	LoadBlockD(1);	LoadBlockD(2);	LoadBlockD(3);

#define	DecryptRound(K,R,id)								\
			t0	   = Fe32##id(x[K  ],0);					\
			t1	   = Fe32##id(x[K^1],3);					\
			DebugDump(x,"",(R)+1,0,0,1,0);					\
			x[K^2] = ROL (x[K^2],1);						\
			x[K^2]^= t0 +   t1 + sk[ROUND_SUBKEYS+2*(R)  ];	\
			x[K^3]^= t0 + 2*t1 + sk[ROUND_SUBKEYS+2*(R)+1];	\
			x[K^3] = ROR (x[K^3],1);						\

#define		Decrypt2(R,id)	{ DecryptRound(2,R+1,id); DecryptRound(0,R,id); }

#if defined(ZERO_KEY)
		switch (key->keyLen)
			{
			case 128:
				for (i=rounds-2;i>=0;i-=2)
					Decrypt2(i,_128);
				break;
			case 192:
				for (i=rounds-2;i>=0;i-=2)
					Decrypt2(i,_192);
				break;
			case 256:
				for (i=rounds-2;i>=0;i-=2)
					Decrypt2(i,_256);
				break;
			}
#else
		{
		Decrypt2(14,_);
		Decrypt2(12,_);
		Decrypt2(10,_);
		Decrypt2( 8,_);
		Decrypt2( 6,_);
		Decrypt2( 4,_);
		Decrypt2( 2,_);
		Decrypt2( 0,_);
		}
#endif
		DebugDump(x,"",0,0,0,0,0);
		if (cipher->mode == MODE_ECB)
			{
#if LittleEndian
#define	StoreBlockD(N)	((DWORD *)outBuffer)[N] = x[N] ^ sk[INPUT_WHITEN+N]
#else
#define	StoreBlockD(N)	{ t0=x[N]^sk[INPUT_WHITEN+N]; ((DWORD *)outBuffer)[N] = Bswap(t0); }
#endif
			StoreBlockD(0);	StoreBlockD(1);	StoreBlockD(2);	StoreBlockD(3);
#undef  StoreBlockD
			DebugDump(outBuffer,"",-1,0,0,0,1);
			continue;
			}
		else
			{
#define	StoreBlockD(N)	x[N]   ^= sk[INPUT_WHITEN+N] ^ IV[N];	\
						IV[N]   = Bswap(((DWORD *)input)[N]);	\
						((DWORD *)outBuffer)[N] = Bswap(x[N]);
			StoreBlockD(0);	StoreBlockD(1);	StoreBlockD(2);	StoreBlockD(3);
#undef  StoreBlockD
			DebugDump(outBuffer,"",-1,0,0,0,1);
			}
		}
	return inputLen;
}

#if ! PGP_OSX	/*	This function doesn't appear to be called	*/
static DWORD TwofishCodeSize(void)
{
	DWORD x= Here(0);
#ifdef USE_ASM
	if (useAsm & 3)
		return TwofishAsmCodeSize();
#endif
	return x - TwofishCodeStart();
}
#endif

/*
 * Exported functions for PGP
 */

static void
twof256Key(void *priv, void const *keymaterial)
{
	keyInstance *key = (keyInstance *)priv;

	key->direction	= DIR_ENCRYPT;	/* Can be reversed later */
	key->keyLen		= 256;
	key->numRounds	= numRounds[(key->keyLen-1)/64];
	memset(key->key32,0,sizeof(key->key32));	/* zero unused bits */

	pgpCopyMemory (keymaterial, key->key32, key->keyLen / 8);

#if UnknownEndian
	if (!EndianKnown)
		setEndian();

	/* key->key32 array must be properly swapped Dwords */
	{ unsigned i;
	for( i=0; i<sizeof(key->key32)/sizeof(DWORD); i++ )
		key->key32[i] = Bswap(key->key32[i]);
	}
#endif

	(void) reKey(key);			/* generate round subkeys */
}

/* This version replicates a bug that was present in Solaris versions
 * prior to June 2002.  We do the byte swapping for the key32 array the
 * opposite of what they should be, i.e. we byte swap on little endian but
 * not on big endian.
 */
static void
twof256KeyBad(void *priv, void const *keymaterial)
{
	keyInstance *key = (keyInstance *)priv;

	key->direction	= DIR_ENCRYPT;	/* Can be reversed later */
	key->keyLen		= 256;
	key->numRounds	= numRounds[(key->keyLen-1)/64];
	memset(key->key32,0,sizeof(key->key32));	/* zero unused bits */

	pgpCopyMemory (keymaterial, key->key32, key->keyLen / 8);

#if UnknownEndian
	if (!EndianKnown)
		setEndian();
	if( ADDR_XOR == 0 )  // means little endian
	{
		unsigned i;
		for( i=0; i<sizeof(key->key32)/sizeof(DWORD); i++ )
			key->key32[i] = ((ROR(key->key32[i],8) & 0xFF00FF00)
							| (ROL(key->key32[i],8) & 0x00FF00FF));
	}
#elif LittleEndian
	{ unsigned i;
	for( i=0; i<sizeof(key->key32)/sizeof(DWORD); i++ )
		key->key32[i] = ((ROR(key->key32[i],8) & 0xFF00FF00)
						| (ROL(key->key32[i],8) & 0x00FF00FF));
	}
#else
/* Do nothing on big endian */
#endif

	(void) reKey(key);			/* generate round subkeys */
}

static void
twof256Encrypt(void *priv, void const *in, void *out)
{
	keyInstance *key = (keyInstance *)priv;
	cipherInstance cipher;

	pgpClearMemory (&cipher, sizeof(cipher));
	cipher.mode = MODE_ECB;

	(void)blockEncrypt (&cipher, key, (PGPByte *)in, BLOCK_SIZE,
						(PGPByte *)out);
}

static void
twof256Decrypt(void *priv, void const *in, void *out)
{
	keyInstance *key = (keyInstance *)priv;
	cipherInstance cipher;

	pgpClearMemory (&cipher, sizeof(cipher));
	cipher.mode = MODE_ECB;

	(void)blockDecrypt (&cipher, key, (PGPByte *)in, BLOCK_SIZE,
						(PGPByte *)out);
}


/*
 * Define a Cipher for the generic cipher.  This is the only
 * real exported thing -- everything else can be static, since everything
 * is referenced through function pointers!
 */
PGPCipherVTBL const cipherTwofish256 = {
	"Twofish256",
	kPGPCipherAlgorithm_Twofish256,
	16,			/* Blocksize */
	32,			/* Keysize */
	sizeof(keyInstance),
	alignof(PGPUInt32),
	twof256Key,
	twof256Encrypt,
	twof256Decrypt,
	NULL
};


/* Buggy version of Twofish, for compatibility with a bug we had on
 * big-endian machines prior to June 2002
 */
PGPCipherVTBL const cipherBadTwofish256 = {
	"BadTwofish256",
	kPGPCipherAlgorithm_BadTwofish256,
	16,			/* Blocksize */
	32,			/* Keysize */
	sizeof(keyInstance),
	alignof(PGPUInt32),
	twof256KeyBad,
	twof256Encrypt,
	twof256Decrypt,
	NULL
};

#endif	/* ] PGP_TWOFISH */



#if UNITTEST




/* Test vectors */

PGPByte K1[] = {
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
	0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
PGPByte P1[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
PGPByte C1[] = {
	0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8,
	0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20
};
PGPByte C1bad[] = {
	0x04, 0xcf, 0xce, 0xf2, 0x75, 0xd4, 0xb4, 0x4f,
	0x17, 0x95, 0xd1, 0x23, 0x22, 0x7e, 0xf4, 0xde
};




int
main(void)
{	/* Test driver for CAST cipher */
	PGPByte priv[sizeof(keyInstance)];
	PGPByte X[16], Y[16];

	twof256Key(priv, K1);
	twof256Encrypt(priv, P1, X);
	if (memcmp(C1, X, sizeof(X)) == 0)
		printf ("Encryption test 1 passed\n");
	else
		printf ("ERROR ON ENCRYPTION TEST 1\n");
	twof256Decrypt(priv, C1, Y);
	if (memcmp(P1, Y, sizeof(Y)) == 0)
		printf ("Decryption test 1 passed\n");
	else
		printf ("ERROR ON DECRYPTION TEST 1\n");

	/* Test "bad" version (backwards compatible with Solaris bug) */
	twof256KeyBad(priv, K1);
	twof256Encrypt(priv, P1, X);
	if (memcmp(C1bad, X, sizeof(X)) == 0)
		printf (PGPTXT_DEBUG8("Encryption test 2 passed\n"));
	else
		printf (PGPTXT_DEBUG8("ERROR ON ENCRYPTION TEST 2\n"));
	twof256Decrypt(priv, C1bad, Y);
	if (memcmp(P1, Y, sizeof(Y)) == 0)
		printf (PGPTXT_DEBUG8("Decryption test 2 passed\n"));
	else
		printf (PGPTXT_DEBUG8("ERROR ON DECRYPTION TEST 2\n"));

	return 0;	/* normal exit */
} /* main */

#endif /* UNITTEST */




/*__Editor_settings____

	Local Variables:
	tab-width: 4
	End:
	vi: ts=4 sw=4
	vim: si
_____________________*/

⌨️ 快捷键说明

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