Я просматривал реализацию Serpent в 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 (ключ, 32 * 8, ks);
Вот это очевидно, что принятый в парам будет 256.
Мне интересно, что другие люди думают об этом? Может ли кто-нибудь еще подтвердить эту ошибку?
TL; DR - http://www.truecrypt.org/bugs/ – CBroe