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

📄 cast5.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		jnz encryptloop	

		/* And we're done!  Pop registers and return */

		pop ebx					/*   U  */
		pop left				/*    V */
		pop right				/*   U  */
		pop esi					/*    V */
		ret						/*   NP */
	}
}

/*
 * dbl decode... plain[i] = cipher[i] ^ CRYPT(cipher[i-2])
 * Can we do this with only one temporary (and still allow in-place)?

 * Crypt cipher[i-2] -> plain[i]
 * Load cipher[i-1] from temp
 * Load cipher[i]
 * Store cipher[i] into temp, plain[i] ^= cipher[i] (or vice-versa)
 * Store plain[i] 
 * i++
 * Um... do we have enough regs?  It seems that we have cipher[i],
 * cipher[i-1] and plain[i] in registers at the same time.

 * Try this order of operations:
 * Crypt cipher[i-2] -> plain[i]
 * Load cipher[i]
 * plain[i] ^= cipher[i]
 * store plain[i]
 * load temp into plain[i], which is now cipher[i-1] (cipher[i-2] after i++)
 * store cipher[i] into temp
 * increment i
 * That works, and doesn't use an excessive number of registers.
 *
 * Written out in full,
 * %eax = src[0];
 * %ecx = src[1];
 * src += 8bytes
 * BSWAP(left)
 * BSWAP(right)
 * right ^= %eax
 * left ^= %ecx
 * dest[0] = right
 * dest[1] = left
 * dest += 8bytes
 * left = in2
 * right = in3
 * in2 = %eax
 * in3 = %ecx
 */

NAKED 
void 
__cdecl 
CAST5decryptCFBdblAsm(
	const PGPUInt32	*xkey, 
	PGPUInt32		iv0, 
	PGPUInt32		iv1, 
	PGPUInt32		iv2, 
	PGPUInt32		iv3, 
	const PGPUInt32	*src, 
	PGPUInt32		*dest, 
	PGPUInt32		len)
{
	__asm
	{
		ALIGN 16

		push esi
		push right

		mov esi, 8+[esp+4]		/*   U  - load key schedule pointer */
		push left				/*    V */
		mov left, 12+[esp+8]	/*   U  - load in0 as left */
		mov right, 12+[esp+12]	/*    V - load in1 as right */

		push ebx				/*   U  */
		xor ebx,ebx				/*    V */

		shl dword ptr 16+[esp+32], 1	/*   NP - double loop counter */

	decryptloop:
		mov eax, [esi]			/*   U  - preload key material */
		mov ecx, [esi+4]		/*    V - preload key material */

		bswap right				/*   NP  */
		bswap left				/*   NP  */

		ROUND(right, left, xor, sub, add, 0)
		ROUND(left, right, sub, add, xor, 1)
		ROUND(right, left, add, xor, sub, 2)
		ROUND(left, right, xor, sub, add, 3)
		ROUND(right, left, sub, add, xor, 4)
		ROUND(left, right, add, xor, sub, 5)
		ROUND(right, left, xor, sub, add, 6)
		ROUND(left, right, sub, add, xor, 7)
		ROUND(right, left, add, xor, sub, 8)
		ROUND(left, right, xor, sub, add, 9)
		ROUND(right, left, sub, add, xor,10)
		ROUND(left, right, add, xor, sub,11)
		ROUND(right, left, xor, sub, add,12)
		ROUND(left, right, sub, add, xor,13)
		ROUND(right, left, add, xor, sub,14)
	/*	ROUND(left, right, xor, sub, add,15)
	 * Last round: omit loading of keys for next round
	 * Instead, start the CFB operations.  Including the
	 * swap of the halves, that ends up as:
	 *
	 * %eax = src[0];
	 * %ecx = src[1];
	 * src += 8bytes
	 * BSWAP(left)
	 * BSWAP(right)
	 * right ^= %eax
	 * left ^= %ecx
	 * dest[0] = right
	 * dest[1] = left
	 * dest += 8bytes
	 * left = in2
	 * right = in3
	 * in2 = %eax
	 * in3 = %ecx
	 */
		add eax, left			/* 1 U  */
		xor edx, edx			/*    V */
		rol eax, cl				/*2-5NP */
		mov bl, ah				/* 6 U  */
		mov dl, al				/*    V */
		shr eax, 16				/* 7 Ux */
		nop						/*    V */
		mov ecx, S1[ebx*4]		/* 8 U  */
		mov bl, ah				/*    V */
		mov edx, S2[edx*4]		/* 9 U  */
		and eax, 255			/*    V */
		xor ecx, edx			/*10 U  */
		mov edx, S3[ebx*4]		/*    V */
		sub ecx, edx			/*11 U  */
		mov edx, S4[eax*4]		/*    V */
		add ecx, edx			/*12 U  */
		mov ebx, 16+[esp+24]	/*    V - fetch src pointer */
		xor right, ecx			/*13 U  */
		add ebx, 8				/*    V - increment src ptr */
		bswap left
  		bswap right
		mov eax, [ebx-8]		/*   U  - get src word */
		mov ecx, [ebx-4]		/*    V - other src word */
		mov 16+[esp+24], ebx	/*   U  - store src pointer back */
		mov edx, 16+[esp+28]	/*    V - fetch dest pointer */
		xor right, eax			/*   U  */
		xor left, ecx			/*    V */
		mov [edx+0], right		/*   U  - store result */
		mov [edx+4], left		/*    V - store result */
		mov left, 16+[esp+16]	/*   U  - fetch in2 for new left */
		mov right, 16+[esp+20]	/*    V - fetch in3 for new right */
		mov 16+[esp+16], eax	/*   U  - store ciphertext for next time */
		mov 16+[esp+20], ecx	/*    V - store ciphertext for next time */
		add edx, 8				/*   U  - increment dest ptr */
		xor ebx, ebx			/*    V - clear %ebx for next iteration */
		dec dword ptr 16+[esp+32]	/*   U  - decrement loop counter (set ZF) */
		mov 16+[esp+28], edx	/*    V - store dest pointer back */
		/* Pairing opportunity lost, sigh */
		jnz decryptloop	

		/* And we're done!  Pop registers and return */

		pop ebx					/*   U  */
		pop left				/*    V */
		pop right				/*   U  */
		pop esi					/*    V */
		ret						/*   NP */
	}
}

#endif	// PGP_INTEL


/////////////////////////
// CAST Testing Functions
/////////////////////////

// VerifyCastSBoxesValid verifies that the CAST S-boxes haven't become
// corrupted in memory.
	
PGPBoolean 
VerifyCastSBoxesValid()
{
	PGPBoolean	valid	= TRUE;
	CRC32		crc		= 0;

	pgpAssert(((PGPUInt32) &S1[0] & 0x3) == 0);
	pgpAssert(((PGPUInt32) &S2[0] & 0x3) == 0);
	pgpAssert(((PGPUInt32) &S3[0] & 0x3) == 0);
	pgpAssert(((PGPUInt32) &S4[0] & 0x3) == 0);
	pgpAssert(((PGPUInt32) &S5[0] & 0x3) == 0);
	pgpAssert(((PGPUInt32) &S6[0] & 0x3) == 0);
	pgpAssert(((PGPUInt32) &S7[0] & 0x3) == 0);
	pgpAssert(((PGPUInt32) &S8[0] & 0x3) == 0);

	crc	= ContinueCRC32(S1, sizeof(S1) / sizeof(S1[0]), crc);
	crc	= ContinueCRC32(S2, sizeof(S2) / sizeof(S2[0]), crc);
	crc	= ContinueCRC32(S3, sizeof(S3) / sizeof(S3[0]), crc);
	crc	= ContinueCRC32(S4, sizeof(S4) / sizeof(S4[0]), crc);
	crc	= ContinueCRC32(S5, sizeof(S5) / sizeof(S5[0]), crc);
	crc	= ContinueCRC32(S6, sizeof(S6) / sizeof(S6[0]), crc);
	crc	= ContinueCRC32(S7, sizeof(S7) / sizeof(S7[0]), crc);
	crc	= ContinueCRC32(S8, sizeof(S8) / sizeof(S8[0]), crc);

	valid = (crc == 0xD8D4C8D7);

	return valid;
}


#if 0	// KEEP [
/*
 * Appendix C.
 * This appendix provides test vectors for the CAST-128 cipher described
 * in Section 5 and in Appendices A and B.
 * C.1. Single Key-Plaintext-Ciphertext Set
 * 128-bit key       = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A (hex)
 * 64-bit plaintext  = 01 23 45 67 89 AB CD EF (hex)
 * 64-bit ciphertext = 23 8B 4F E5 84 7E 44 B2 (hex)
 * C.2. Full Maintenance Test
 * A maintenance test for CAST-128 has been defined to verify the correctness
 * of implementations.  It is defined in pseudo-code as follows, where a and
 * b are 128-bit vectors, aL and aR are the leftmost and rightmost halves of
 * a, bL and bR are the leftmost and rightmost halves of b, and encrypt(d,
 * k) is the encryption in ECB mode of block d under key k.
 * 
 * .
 * Initial 
 * a = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A (hex)
 * Initial 
 * b = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A (hex)
 * do 1,000,000 times
 * {
 *     aL = encrypt( aL , b)
 *     aR = encrypt( aR , b)
 *     bL = encrypt( bL , a)
 *     bR = encrypt( bR , a)
 * }
 * Verify 
 * a == EE A9 D0 A2 49 FD 3B A6 B3 43 6F B8 9D 6D CA 92 (hex)
 * Verify 
 * b == B2 C9 5E B0 0C 31 AD 71 80 AC 05 B8 E8 3D 69 6E (hex)
 * 	
 * 
 */

#include <stdio.h>
#include <strings.h>

void 
printhex(const char *msg, const PGPUInt8 *num, int len)
{
	int i;

	printf(msg);

	for (i=0; i<len; i++)
		printf("%X", num[i]);

	printf("\n");
}

int
main(void)
{
	PGPUInt8 a[16] = 
	{
		0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
		0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
	};
	PGPUInt8 b[16] = 
	{
		0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
		0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
	};
	PGPUInt8 test[8] =
	{
		0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
	};
	static PGPUInt8 const expect1[8] =
	{
		 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2
	};
	static PGPUInt8 const expecta[16] =
	{
		0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6,
		0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92
	};
	static PGPUInt8 const expectb[16] =
	{
		0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71,
		0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E
	};
	PGPUInt32	xkey[32];
	long	count;
	printf("Simple sanity check...\n");
	
	printhex("       Key =", a, sizeof(a));
	CAST5schedule(xkey, a);
	printhex(" Plaintext =", test, sizeof(test));
	CAST5encrypt(test, test, xkey);
	printhex("Ciphertext =", test, sizeof(test));
	printhex("    Expect =", expect1, sizeof(expect1));
	if (memcmp(test, expect1, sizeof(test)) != 0)
		printf("		***** ERROR *****\n");
	
	printf("Full maintenance test (4,000,000 encryptions)...\n");
	for (count = 0 ;count < 1000000; count++) {
		CAST5schedule(xkey, b);
		CAST5encrypt(a, a, xkey);
		CAST5encrypt(a+8, a+8, xkey);
		CAST5schedule(xkey, a);
		CAST5encrypt(b, b, xkey);
		CAST5encrypt(b+8, b+8, xkey);
	}
	printhex("     a =", a, sizeof(a));
	printhex("Expect =", expecta, sizeof(expecta));
	if (memcmp(a, expecta, sizeof(a)) != 0)
		printf("		***** ERROR *****\n");
	printhex("     b =", b, sizeof(b));
	printhex("Expect =", expectb, sizeof(expectb));
	if (memcmp(b, expectb, sizeof(b)) != 0)
		printf("		***** ERROR *****\n");
	{
		char bob[1];
		gets(bob);
	}

	return 0;
}

#endif	// ] KEEP

⌨️ 快捷键说明

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