2014-03-02 35 views
3

我在浏览蛇实施TrueCrypt加密(7.1A)和一些看起来不正确的!这里是这个算法的接口:TrueCrypt的错误在蛇实施

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

我很好奇别人怎么想这件事?任何人都可以证实这个错误吗?

+0

TL; DR - http://www.truecrypt.org/bugs/ – CBroe

回答

3

由于VeraCrypt主要开发者,因为VeraCrypt基于TrueCrypt加密源的用户重定向我到这个职位。

研究你提出这个问题后,我可以证实,这确实是在代码中的错误和调用serpent_set_key要经过32而不是256作为参数。

幸运的是,这个错误对程序执行过程中的正确性或安全性没有影响,这就是为什么没有人在你面前发现它。因此,我们不能将其视为错误。

让我在三点解释:

  1. 让我们来看看Serpent算法实现的serpent_set_key:参数keylen仅用于复制用户钥匙插入ks缓冲区是保证有最小尺寸为(看crypt.h中定义的SERPENT_KS)。因此,即使keylen是256而不是32,我们也不会超出ks的分配内存。
  2. 这个循环后到来将建立使用膨胀蛇键的前32个字节的用户钥仅如蛇算法规范内部密钥扩展。因此,在前32个之后的所有字节将被丢弃,并且它们将不会被使用。这就解释了为什么计算结果是正确的,即使传递了256字节而不是预期的32字节。
  3. 如果我们列出所有运行时调用导致serpent_set_key我们会发现,除了自动测试的情况下,所有的呼叫使用,即使它的第32个字节填充USERKEY参数256个字节的缓冲区(看在crypto.h中的MASTER_KEYDATA_SIZE)。因此,在运行时,我们永远不会读取分配缓冲区空间之外的内容。它仍然是自动测试(在Tests.c中的ei或在Dlgcode.c中的CipherTestDialogProc),其中32字节的缓冲区用于userKey:这里我们将读取超出分配的空间,但实际上它不会造成任何伤害,因为该缓冲区周围的内存是可读的。

我希望这阐明为什么这个错误是无害的。这就是说,它必须得到纠正,这就是我们在VeraCrypt中要做的。

为了记录在案,看来这个错误是由twofish_set_keyserpent_set_key之间的混淆造成的:两个函数的声明具有相同类型的参数,但twofish_set_key预计用户密钥长度位,而serpent_set_key指望它在字节!显然,我们应该对密钥的大小有相同的约定。

+0

好的我同意这个问题不会影响程序的正常运行,但它至少是干净的算法实现中的一个错误! – user3369634

+0

我犯了一个修复的这VeraCrypt(https://sourceforge.net/p/veracrypt/code/ci/86abdb1b12e855d1b92c103446b2cadf9c4e57a3/)。实际上,由于我们只使用固定大小的键(256位),所以我除去了解决问题的密钥长度参数,而且还最小化了对引导加载程序非常重要的代码大小(我们正在努力使其尽可能小为了能够添加新的功能)。 –