Previous Entry Share Next Entry
2016-01

It is impossible to safely implement any cryptosystem providing forward secrecy in C.

TLDR: Все без исключения реализации AES (ну и наверное многих других симметричных шифров) на C потенциально уязвимы к утечке ключей (а-ля Heartbleed, например), из-за того, что C, будучи портабельным ассемблером, абстрагирует от нас возможность надежно очистить память.

http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.html

Ну что, плюс один повод перенести системное программирование на какой-то еще язык.
Можно, конечно, повкручивать очередных прагм, или выпустить C0x, но общую проблему это не исправит, т.к. изменения в модели памяти не будут обратносовместимы.

Альтернативно, можно расслабиться и продолжать писать крипто на JS (помнится, его всячески критиковали за невозможность стереть ключи), раз уж в остальных местах всё столь же плохо.

UPD: Пример проблемы - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=8537

This entry was originally posted at http://wizzard.dreamwidth.org/389868.html. It has comment count unavailable comments. Please comment there using OpenID.

  • 1
dennis_chikin September 8th, 2014
Вообще мне казалось, что если кто-то может свободно запускаться, гулять по памяти и что-то куда-то передавать - он точно так же может делать что угодно еще.

wizzard0 September 8th, 2014
Ммммм, тут проблема не в этом.

Проблема в том, что нельзя написать *модуль* (функцию, shared library, whatever) и гарантировать, что его данные изолированы в нём самом.

Т.о. получается, что минимальный "security boundary" это процесс, даже не thread и не function.

Ну и работать с ключами в монолитном ядре ОС из-за этого становится очень сложно.

Edited at 2014-09-08 05:33 pm (UTC)

(no subject) (Anonymous) Expand
_winnie September 8th, 2014
Можно спускаться ещё на уровни ниже:

* что процессор по другому греется в зависимости от ключа и другие конденсаторы заряжает, и кеш-линии внутри процессора не очищаются.

* что виртуальная машина выполняющая код - была за-swap-лена на диск в самый неподходящий момент.

* что нейроны в моей голове хранят отпечаток пароля

Но можно думать об усложении жизни взломщику (и дороговизне атаки в долларах), а не о принципиальной невозможности стирания пароля из этой вселенной.

nponeccop September 8th, 2014
Ну, статья говорит о том, что, как ни странно, в Си нет способа уничтожить данные.

Был бы такой способ, можно было стереть ключи и не париться.

А оказывается, простого и работающего решения нет. Конечно, мы не умрём - "можно думать об усложении жизни взломщику".

Из списка атак почти ничего не актуально, разбирать по пунктам лень.

sleepy_drago September 8th, 2014
странно ожидать одновременно "portable" и "aesni". И хоть я никогда не буду подходить к секьюрити даже с длинной палкой, я думаю этот товарищ передергивает по самое немогу.

wizzard0 September 8th, 2014
в модели памяти и в стандарте нет операции "уничтожить данные". есть только "сделать так, чтобы такое-то выражение стало возвращать Х с точки зрения внутреннего наблюдателя", а что происходит с точки зрения стороннего наблюдателя - произвол оптимизатора.

Edited at 2014-09-08 08:20 pm (UTC)

kunaifusu September 8th, 2014
Странные проблемы у чувака. Очевидно, что в portable C то что он хочет - невозможно в принципе потому что portable C может скомпилироваться в инструкции для индусиков со счетами а не в инструкции для процессора. А в реальном C никаких проблем написать библиотеку чтобы нюкала контекст функции нет. Я писал чуть сложнее - собирал контексты со всем колстэком, на трёх разных платформах за неделю.

wizzard0 September 8th, 2014
> в реальном C никаких проблем написать библиотеку чтобы нюкала контекст функции нет.
потом выходит новый апдейт gcc, и нюкалка перестает быть таковой, вот про что чувак жалуется.

(no subject) (Anonymous) Expand
amarao_san September 8th, 2014
Я уверен, что в других языках ситуация ещё более аховая - просто потому, что запрос в данном случае совершенно не соответствует обычному требованию к языку. И любой суперпонтовый хаскель или go в этом вопросе будет ничем не лучше - он так же может сложить значения в неожиданные регистры или "соптимизировать" математику через стек.

wizzard0 September 9th, 2014
В спеках Ada, Rust и Eiffel это дело точно было.

sab123 September 8th, 2014
Очевидно, что в Си как таковом такой способ есть. Проблемы - в зло*бучих оптимизаторах, чьих создателей повбывать бы и засунуть им ихнюю оптимизацию в жопу. Но на самом деле и в них - тоже такой способ есть. Всех делов - взять указатель на volatile и очищать через него.

nicka_startcev September 8th, 2014
>Проблемы - в зло*бучих оптимизаторах

которые имеют право делать так, как завещал зло*бучий стандарт, который афтыри кода не читали и игнорируют? да, есть такая проблема.

sab123 September 8th, 2014
Почитав более внимательно, они пишут про стек. Ну, тоже не проблема. Делается примерно так:

encrypt(...)
{
  volatile char *stackfrom, *stackto;

  do_encrypt(&stackfrom, &stackto, ...)

  if (stackfrom < stackto) {
    for (;stackfrom < stackto; stackfrom++)
      *stackfrom = 0;
  } else {
    for (;stackto < stackfrom; stackto++)
      *stackto = 0;
  }
}

do_encrypt(volatile char** stackfrom, volatile char **stackto, ...)
{
   ...
   *stackto = (char*)&stackto;
   get_stack_from(stackfrom);
}

get_stack_from(volatile char **stackfrom)
{
  volatile char reserve[10000];
  *stackfrom = reserve + sizeof(reserve)/2;
}


Найти указатели стека до вызова и в самой глубокой его точке (и с неким запасом между ними), и зафигачить туда нули вручную. Написанное должно быть более-менее портабельно для стеков, растущих хоть вниз хоть вверх. Есть некая потенциальная возможность неприятностей с регистровыми значениями, которые окажутся вытолкнутыми в память перед циклом затирания, что они тоже затрутся, но это должно обходиться хранением всего важного в памяти, которую объявить volatile.

wizzard0 September 9th, 2014
Register spilling не обязан происходить в стэк. В текущих реализациях - да, происходит. Но не обязан.

Ну и вопрос о хвостах в XMM регистрах остается открытым.

kodt_rsdn September 9th, 2014
Tldr, но для параноиков, на си написать виртуальную машинку, которая не оптимизирует лишнего и чистит память за ключом и исходной строкой.

wizzard0 September 9th, 2014
Ээээ, и чем это поможет?

mbr September 9th, 2014
> C, будучи портабельным ассемблером, абстрагирует от нас возможность надежно очистить память.

Бред какой-то. Во всех эмбеддед реализациях, что я копал, вся память выделяется в динамической памяти, потом принудительно обнуляется.

wizzard0 September 9th, 2014
Ключевое слово "реализациях".

Алсо, почитай статью по ссылке. Да, и при чем тут эмбед вообще? :)

Edited at 2014-09-09 05:07 am (UTC)

mbr September 9th, 2014
Проблема явно надумана. Пока дойдет до злоумышленника, стек и регистры будут трижды потерты, даже если там чего-то останется.

Алсо, товарищ не в курсе про volatile register.

Для особых параноиков можно сделать ассемблерные инлайны перед и после вызовов.

Но изобретать новый язык из-за надуманной проблемы - товарищ жгет.

wizzard0 September 9th, 2014
> volatile register.
ну давай, сложи в volatile register RSA ключ. На 4096 бит.

> надуманной проблемы
"для моих задач эта проблема неактуальна, значит - она надумана".

sorhed September 9th, 2014
Заглянул посмотреть на ФОКСТРОТ цешников. Я не ошибся!

wizzard0 September 10th, 2014
Hell yeah!

kvqa September 9th, 2014
SecureZeroMemory разве проблему не решает?
Общее адресное пространство остается, конечно, но вот проблемы с занулением какие-то совсем надуманные имхо.

wizzard0 September 9th, 2014
Нет, поскольку оптимизатор может копировать эту самую память произвольно. Но с szm, конечно, гораздо лучше, чем без.

anonim_legion September 10th, 2014
Не писал ничего подобного, но вот в виндах я могу выделить блок памяти в через VirtualAlloc, и ключ хранить только в нем, и код по работе с ключом туда же засунуть. Уж не помню, можно ли защитить блок от сброса в своп, вроде тоже что-то такое было.

То есть, если язык не решает некий вопрос, то сочетание язык+возможности ОС решают.

wizzard0 September 10th, 2014
Этого недостаточно, т.к. оптимизатор может этот блок скопировать куда захочет, если это ускорит выполнение программы.

  • 1
?

Log in

No account? Create an account