📄 pgpcast5.c
字号:
PGPUInt32 l, r, t;
r = (PGPUInt32)
in[0]<<24 | (PGPUInt32)in[1]<<16 | (PGPUInt32)in[2]<<8 | in[3];
l = (PGPUInt32)
in[4]<<24 | (PGPUInt32)in[5]<<16 | (PGPUInt32)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);
}
/*
* Exported functions
*/
/* Expand 16 byte key into expanded key *priv */
static void
cast5Key(void *priv, void const *key)
{
CAST5schedule((PGPUInt32 *)priv, (const PGPByte *) key);
}
/* Encrypt 8 bytes at *in into 8 bytes at *out using key sched from *priv */
static void
cast5Encrypt(void *priv, void const *in, void *out)
{
CAST5encrypt((const PGPByte *) in, (PGPByte *) out, (PGPUInt32 *)priv);
}
/* Decrypt 8 bytes at *in into 8 bytes at *out using key sched from *priv */
static void
cast5Decrypt(void *priv, void const *in, void *out)
{
CAST5decrypt( (const PGPByte *) in, (PGPByte *) out, (PGPUInt32 *)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(PGPByte *hash, PGPByte const *buf, PGPUInt32 *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, void const *bufIn, PGPSize len)
{
PGPSize i;
PGPByte hash[32];
PGPUInt32 *xkey = (PGPUInt32 *)priv;
PGPByte *buf = (PGPByte *) bufIn;
/* Read out the key in canonical byte order for the IV */
for (i = 0; i < 8; i++) {
hash[2*i] = (PGPByte)(xkey[i]>>8);
hash[2*i+1] = (PGPByte)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) {
pgpClearMemory(hash+24+i, 8-i);
CAST5StepTandemDM(hash, hash+24, xkey);
i = 0;
}
pgpClearMemory(hash+24+i, 6-i);
hash[30] = (PGPByte)(len >> 8);
hash[31] = (PGPByte)len;
CAST5StepTandemDM(hash, hash+24, xkey);
/* Re-schedule the key */
CAST5schedule(xkey, hash);
pgpClearMemory( hash, sizeof(hash));
}
/*
* 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 cipherCAST5 =
{
"CAST5",
kPGPCipherAlgorithm_CAST5,
8, /* Blocksize */
16, /* Keysize */
CAST5_KEYBYTES, /* Priv array size */
alignof(PGPUInt32),
cast5Key,
cast5Encrypt,
cast5Decrypt,
cast5Wash
};
#if UNITTEST
/*
* From RFC2144:
*
* Appendix B. Test Vectors
*
* This appendix provides test vectors for the CAST-128 cipher described
* this document.
*
* B.1. Single Plaintext-Key-Ciphertext Sets
*
* In order to ensure that the algorithm is implemented correctly, the
* following test vectors can be used for verification (values given in
* hexadecimal notation).
*
* 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A
* plaintext = 01 23 45 67 89 AB CD EF
* ciphertext = 23 8B 4F E5 84 7E 44 B2
*
* 80-bit key = 01 23 45 67 12 34 56 78 23 45
* = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00
* plaintext = 01 23 45 67 89 AB CD EF
* ciphertext = EB 6A 71 1A 2C 02 27 1B
*
* 40-bit key = 01 23 45 67 12
* = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
* plaintext = 01 23 45 67 89 AB CD EF
* ciphertext = 7A C8 16 D1 6E 9B 30 2E
*
* B.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)
*
*/
/* Test vectors */
PGPByte K1[] = {
0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};
PGPByte P1[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
};
PGPByte C1[] = {
0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2
};
#if 0
/*
* We do not support 80-bit and lower keys, which require 12 rather
* than 16 rounds of encryption.
*/
PGPByte K2[] = {
0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
PGPByte P2[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
};
PGPByte C2[] = {
0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B
};
PGPByte K3[] = {
0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
PGPByte P3[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
};
PGPByte C3[] = {
0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E
};
#endif
/* Maintenance test */
PGPByte A[] = {
0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};
PGPByte B[] = {
0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};
PGPByte VA[] = {
0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6,
0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92
};
PGPByte VB[] = {
0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71,
0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E
};
int
main(void)
{ /* Test driver for CAST cipher */
int i;
PGPByte priv[CAST5_KEYBYTES];
PGPByte X[8], Y[8];
/* First test */
cast5Key(priv, K1);
cast5Encrypt(priv, P1, X);
if (memcmp(C1, X, sizeof(X)) == 0)
printf ("Encryption test 1 passed\n");
else
printf ("ERROR ON ENCRYPTION TEST 1\n");
cast5Decrypt(priv, C1, Y);
if (memcmp(P1, Y, sizeof(Y)) == 0)
printf ("Decryption test 1 passed\n");
else
printf ("ERROR ON DECRYPTION TEST 1\n");
/* Maintenance test */
printf ("Performing maintenance test...\n");
for (i=0; i<1000000; ++i) {
cast5Key(priv, B);
cast5Encrypt(priv, A, A);
cast5Encrypt(priv, A+8, A+8);
cast5Key(priv, A);
cast5Encrypt(priv, B, B);
cast5Encrypt(priv, B+8, B+8);
}
if (memcmp(A, VA, sizeof(A)) == 0)
printf ("Maintenance test A passed\n");
else
printf ("ERROR ON MAINTENANCE TEST A\n");
if (memcmp(B, VB, sizeof(B)) == 0)
printf ("Maintenance test B passed\n");
else
printf ("ERROR ON MAINTENANCE TEST B\n");
return 0; /* normal exit */
} /* main */
#endif /* UNITTEST */
#endif /* ] PGP_CAST5 */
/*__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 + -