📄 cast5.cpp
字号:
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 + -