2014-03-02 4 views
3

Я просматривал реализацию 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.

Мне интересно, что другие люди думают об этом? Может ли кто-нибудь еще подтвердить эту ошибку?

+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 буфер, который гарантированно иметь минимальный размер (см. определение SERPENT_KS в crypt.h). Таким образом, даже если keylen составляет 256 вместо 32, мы не будем писать за выделенной памятью ks.
  2. Внутреннее расширение ключа, которое появляется после этого цикла, будет создавать расширенный ключ Змеи, используя первые 32 байта пользователяKey только, как в спецификации алгоритма Змея. Таким образом, все байты, следующие после первых 32, будут отброшены, и они никогда не будут использоваться.Это объясняет, почему результат вычисления верен, даже если 256 байтов переданы ему вместо ожидаемых 32 байтов.
  3. Если мы перечислим все вызовы во время выполнения, приводит к serpent_set_key, мы заметим, что, за исключением случаев автоматических тестов, все вызовы используют буфер 256 байтов для параметра userKey, даже если его первые 32 байта заполнены (посмотрите на MASTER_KEYDATA_SIZE в crypto.h). Таким образом, во время выполнения мы никогда не будем читать за пределами пространства буфера распределения. Это остается в случае автоматических тестов (ei в Tests.c или CipherTestDialogProc в Dlgcode.c), где для userKey используется буфер с 32 байтами: здесь мы будем читать за пределами выделенного пространства, но на практике это не наносит никакого вреда, память вокруг этого буфера читаема.

Надеюсь, это разъяснит, почему эта ошибка безвредна. Это, как говорится, должно быть исправлено, и это то, что мы будем делать в VeraCrypt.

Для записи, кажется, что эта ошибка была вызвана путаницей между twofish_set_key и serpent_set_key: декларация два функций имеет один и тот же тип параметров, но twofish_set_key ожидает, что длина ключа пользователя в битах, тогда как serpent_set_key ожидают его в байт! Очевидно, что мы должны иметь такое же соглашение для размера ключа.

+0

OK Я согласен с тем, что эта проблема не влияет на нормальный запуск программы, однако это, по крайней мере, ошибка в чистой реализации алгоритма ! – user3369634

+0

Я исправил это для VeraCrypt (https://sourceforge.net/p/veracrypt/code/ci/86abdb1b12e855d1b92c103446b2cadf9c4e57a3/). Фактически, поскольку мы используем только фиксированные ключи размера (256 бит), я полностью удалял параметр длины ключа, который решает проблему, но также минимизирует размер кода, который очень важен для загрузчика (мы изо всех сил стараемся сделать его как можно меньше в чтобы иметь возможность добавлять новые функции). –

 Смежные вопросы

  • Нет связанных вопросов^_^