我正在浏览 TrueCrypt (7.1a) 中的 Serpent 实现,但看起来有些不对劲!这是该算法的接口:
void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks);
void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks);
void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks);
这里感兴趣的函数是serpent_set_key
。用户密钥长度为 32 个字节,keylen
应该是它的大小,而ks
是用于加密/解密的输出密钥。问题是执行。这是开头的相关片段:
unsigned __int32 a,b,c,d,e;
unsigned __int32 *k = (unsigned __int32 *)ks;
unsigned __int32 t;
int i;
for (i = 0; i < keylen / (int)sizeof(__int32); i++)
k[i] = LE32(((unsigned __int32*)userKey)[i]);
for 循环实际上是将数据从用户键复制到实现键。它是通过将数据“查看”为 4 字节整数来完成的。现在,如果密钥 len 作为字节发送(32 是正确的值),那么一切都很好,但是......
在 trueCrypt 的所有实现中,这在两个地方被调用。这是第一个:在 CipherInit 中是这样调用的:
case SERPENT:
serpent_set_key (key, CipherGetKeySize(SERPENT) * 8, ks);
break;
CipherGetKeySize(SERPENT)
将返回 32(字节),因此传入的参数的值为 256!就密钥的长度而言,这是正确的,但不适用于此实现!这将导致 'serpent_set_key' 中的缓冲区溢出,因为 for 循环将运行 64 次而不是仅 8 次!另一个调用它的地方是在 EAInit 中,如下所示:
serpent_set_key (key, 32 * 8, ks);
很明显,传入的参数将是 256。
我很好奇其他人对此有何看法?其他人可以确认这个错误吗?