pgpcast5.c

来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 483 行 · 第 1/2 页

C
483
字号
#undef z1
#undef z2
#undef z3
#undef z4
#undef z5
#undef z6
#undef z7
#undef z8
#undef z9
#undef zA
#undef zB
#undef zC
#undef zD
#undef zE
#undef zF

/* Some macros used in the encryption/decryption code */
#define ROL(x,r) ((x)<<(r) | (x)>>(32-(r)))

#ifdef __GNUC__
#if __i386__
/* Redefine using GCC inline assembler */
#undef ROL
#define ROL(x,r)	\
	({unsigned _y;	\
	__asm__("rol %%cl,%0" : "=g" (_y) : "0" (x), "c" (r)); _y;})
#endif /* __i386__ */
#endif /* __GNUC__ */

#define F1(x,xkey,i) (ROL((xkey)[2*(i)] + (x), (xkey)[2*(i)+1]))
#define F2(x,xkey,i) (ROL((xkey)[2*(i)] ^ (x), (xkey)[2*(i)+1]))
#define F3(x,xkey,i) (ROL((xkey)[2*(i)] - (x), (xkey)[2*(i)+1]))

#define G1(x) (((S1[B0(x)] ^ S2[B1(x)]) - S3[B2(x)]) + S4[B3(x)])
#define G2(x) (((S1[B0(x)] - S2[B1(x)]) + S3[B2(x)]) ^ S4[B3(x)])
#define G3(x) (((S1[B0(x)] + S2[B1(x)]) ^ S3[B2(x)]) - S4[B3(x)])

/*
* Encrypt the 8 bytes at *in into the 8 bytes at *out using the expanded
* key schedule from *xkey.
*/
static void
CAST5encrypt(byte const *in, byte *out, word32 const *xkey)
{
	word32 l, r, t;

	l = (word32)in[0]<<24 | (word32)in[1]<<16 | (word32)in[2]<<8 | in[3];
	r = (word32)in[4]<<24 | (word32)in[5]<<16 | (word32)in[6]<<8 | in[7];

		t = F1(r, xkey, 0); l ^= G1(t);
		t = F2(l, xkey, 1); r ^= G2(t);
		t = F3(r, xkey, 2); l ^= G3(t);
		t = F1(l, xkey, 3); r ^= G1(t);
		t = F2(r, xkey, 4); l ^= G2(t);
		t = F3(l, xkey, 5); r ^= G3(t);
		t = F1(r, xkey, 6); l ^= G1(t);
		t = F2(l, xkey, 7); r ^= G2(t);
		t = F3(r, xkey, 8); l ^= G3(t);
		t = F1(l, xkey, 9); r ^= G1(t);
		t = F2(r, xkey, 10); l ^= G2(t);
		t = F3(l, xkey, 11); r ^= G3(t);
		/* Stop here if only doing 12 rounds */
		t = F1(r, xkey, 12); l ^= G1(t);
		t = F2(l, xkey, 13); r ^= G2(t);
		t = F3(r, xkey, 14); l ^= G3(t);
		t = F1(l, xkey, 15); r ^= G1(t);

		out[0] = B0(r);
		out[1] = B1(r);
		out[2] = B2(r);
		out[3] = B3(r);
		out[4] = B0(l);
		out[5] = B1(l);
		out[6] = B2(l);
		out[7] = B3(l);
}

#if 0
/* Unused at present */

/*
* Decrypt the 8 bytes at *in into the 8 bytes at *out using the expanded
* key schedule from *xkey.
*/
static void
CAST5decrypt(byte const *in, byte *out, word32 const *xkey)
{
		word32 l, r, t;

		r = (word32)in[0]<<24 | (word32)in[1]<<16 | (word32)in[2]<<8 | in[3];
		l = (word32)in[4]<<24 | (word32)in[5]<<16 | (word32)in[6]<<8 | in[7];

		t = F1(l, xkey, 15); r ^= G1(t);
		t = F3(r, xkey, 14); l ^= G3(t);
		t = F2(l, xkey, 13); r ^= G2(t);
		t = F1(r, xkey, 12); l ^= G1(t);
		/* Start here if only doing 12 rounds */
		t = F3(l, xkey, 11); r ^= G3(t);
		t = F2(r, xkey, 10); l ^= G2(t);
		t = F1(l, xkey, 9); r ^= G1(t);
		t = F3(r, xkey, 8); l ^= G3(t);
		t = F2(l, xkey, 7); r ^= G2(t);
		t = F1(r, xkey, 6); l ^= G1(t);
		t = F3(l, xkey, 5); r ^= G3(t);
		t = F2(r, xkey, 4); l ^= G2(t);
		t = F1(l, xkey, 3); r ^= G1(t);
		t = F3(r, xkey, 2); l ^= G3(t);
		t = F2(l, xkey, 1); r ^= G2(t);
		t = F1(r, xkey, 0); l ^= G1(t);

		out[0] = B0(l);
		out[1] = B1(l);
		out[2] = B2(l);
		out[3] = B3(l);
		out[4] = B0(r);
		out[5] = B1(r);
		out[6] = B2(r);
		out[7] = B3(r);
}
#endif

/*
* Exported functions
*/

/* Expand 16 byte key into expanded key *priv */
static void
cast5Key(void *priv, byte const *key)
{
	CAST5schedule((word32 *)priv, key);
}

/* Encrypt 8 bytes at *in into 8 bytes at *out using key sched from *priv */
static void
cast5Encrypt(void *priv, byte const *in, byte *out)
{
	CAST5encrypt(in, out, (word32 *)priv);
}



/*
* Do one 64-bit step of a Tandem Davies-Meyer hash computation.
* The hash buffer is 32 bytes long and contains H (0..7), then G (8..15),
* then 16 bytes of scratch space. The buf is 8 bytes long.
* xkey is a temporary key schedule buffer.
* This and the extra data in the hash buffer are allocated by the
* caller to reduce the amount of buffer-wiping we have to do.
* (It's only called from ideaWash, so the interface can be a bit
* specialized.)
*/
static void
CAST5StepTandemDM(byte *hash, byte const *buf, word32 *xkey)
{
		int i;

		/* key1 = G << 64 + M, remembering that CAST is big-endian */
		memcpy(hash+16, buf, 8);
		CAST5schedule(xkey, hash+8);
		/* W = E_key1(H), key2 = M << 64 + W */
		CAST5encrypt(hash, hash+24, xkey);
		CAST5schedule(xkey, hash+16);
		/* V = E_key2(G) */
		CAST5encrypt(hash+8, hash+16, xkey);
		/* H ^= W, G ^= V */
		for (i = 0; i < 8; i++) {
				hash[i] ^= hash[i+24];
				hash[i+8] ^= hash[i+16];
		}
}

/*
* Munge the key of the CipherContext based on the supplied bytes.
* This is for random-number generation, so the exact technique is
* unimportant, but it happens to use the current key as the
* IV for computing a tandem Davies-Meyer hash of the bytes,
* and uses the output as the new key.
*/
static void
cast5Wash(void *priv, byte const *buf, unsigned len)
{
		unsigned i;
		byte hash[32];
		word32 *xkey = (word32 *)priv;

		/* Read out the key in canonical byte order for the IV */
		for (i = 0; i < 8; i++) {
			hash[2*i] = (byte)(xkey[i]>>8);
			hash[2*i+1] = (byte)xkey[i];
		}

		/* Do the initial blocks of the hash */
		i = len;
		while (i >= 8) {
				CAST5StepTandemDM(hash, buf, xkey);
				buf += 8;
				i -= 8;
		}
		/*
		* At the end, we do Damgard-Merkle strengthening, just like
		* MD5 or SHA. Pad with 0x80 then 0 bytes to 6 mod 8, then
		* add the length. We use a 16-bit length in bytes instead
		* of a 64-bit length in bits, but that is cryptographically
		* irrelevant.
		*/
		/* Do the first partial block - i <= 7 */
		memcpy(hash+24, buf, i);
		hash[24 + i++] = 0x80;
		if (i > 6) {
			memset(hash+24+i, 0, 8-i);
			CAST5StepTandemDM(hash, hash+24, xkey);
			i = 0;
		}
		memset(hash+24+i, 0, 6-i);
		hash[30] = (byte)(len >> 8);
		hash[31] = (byte)len;
		CAST5StepTandemDM(hash, hash+24, xkey);

		/* Re-schedule the key */
		CAST5schedule(xkey, hash);

		memset(hash, 0, sizeof(hash));
}

/*
* Define a struct Cipher for the generic cipher. This is the only
* real exported thing -- everything else can be static, since everything
* is referenced through function pointers!
*/
struct PgpCipher const cipherCAST5 = {
		"CAST5",
		PGP_CIPHER_CAST5,
		8,				/* Blocksize */
		16,		 		/* Keysize */
		CAST5_KEYBYTES,							/* Priv array size */
		alignof(word32),
		cast5Key,
		cast5Encrypt,
		cast5Wash
};

⌨️ 快捷键说明

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