Как известно, у /dev/random, криптографически стойкого генератора псевдослучайных чисел (CSPRNG), имеется одна неприятная проблема – блокировки. В данной статье рассказывается, каким образом можно ее решить.

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

Энди Лутомирски (Andy Lutomirski) опубликовал третью версию патча в конце декабря. Он вносит «два основных семантических изменения в случайных API Linux». Патч добавляет новый флаг GRND_INSECURE к системному вызову getrandom() (хотя Лутомирский обращается к нему как к getentropy(), который реализован в glibc с помощью getrandom() с фиксированными флагами); этот флаг заставляет вызов всегда возвращать количество запрошенных данных, но без гарантии, что эти данные случайны. Ядро просто приложит все усилия, чтобы дать наилучшие случайные данные, которые у него есть на данный момент времени. «Вероятно, лучшее, что можно сделать, это назвать его „INSECURE“ (небезопасным), чтобы воспрепятствовать использованию этого API для вещей, которые нуждаются в безопасности».

Патчи также удаляют блокирующий пул. В настоящее время ядро поддерживает два пула случайных данных, один из которых соответствует /dev/random, а другой — /dev/urandom, как описано в этой статье 2015 года. Блокирующий пул — это пул для /dev/random; чтение для этого устройства будет блокироваться (имеется в виду его имя) до тех пор, пока из системы не будет собрана «достаточная» энтропия для удовлетворения запроса. Дальнейшие чтения из этого файла также блокируются, если в пуле недостаточно энтропии.

Удаление пула блокировок означает, что чтение из /dev/random ведет себя как getrandom() со значением flags равным нулю (и превращает флаг GRND_RANDOM в noop). После инициализации криптографического генератора случайных чисел (CRNG), чтение из /dev/random и вызовы getrandom(...,0) не приведет к блокировке и вернет запрошенное количество случайных данных.

Лутомирский говорит: «Я считаю, что блокирующий пул Linux изжил себя. CRNG Linux генерирует выходные данные, которые достаточно хороши, чтобы использовать их даже для генерации ключей. Блокирующий пул не является более сильным в любом материальном отношении, и для его поддержания требуется много инфраструктуры сомнительной ценности».

Изменения были сделаны с прицелом на то, чтобы существующие программы действительно не пострадали, и на самом деле, проблем с длительным ожиданием таких вещей, как генерация ключей GnuPG, станет поменьше.

«Эти серии не должны нарушать никаких существующих программ. /dev/urandom остается неизменным. /dev/random по-прежнему блокируется сразу после загрузки, но блокируется меньше, чем раньше. getentropy () с существующими флагами вернет результат, который будет таким же подходящим для практических целей, как и раньше».

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

Штефан Мюллер (Stephan Müller) предположил, что его набор патчей для генератора случайных чисел Linux (LRNG) (в настоящее время выпущена 26 версия) может быть способом предоставления истинных случайных чисел для приложений, которые в этом нуждаются. LRNG «полностью соответствует требованиям «Рекомендаций по источникам энтропии, используемым для генерации случайных битов» SP800-90B», что делает его решением проблемы государственных стандартов.
Мэтью Гарретт (Matthew Garrett) возражал против термина «истинные случайные данные», отмечая, что выбираемые устройства в принципе могут быть смоделированы достаточно точно, чтобы сделать их предсказуемыми: «мы здесь не отбираем квантовые события».

Мюллер ответил, что этот термин происходит от немецкого стандарта AIS 31 для описания генератора случайных чисел, который только выдает результат «с такой же скоростью, с какой базовый источник шума производит энтропию».

Помимо разночтений терминологии, наличие пула блокировки, как это предлагается патчами LRNG, просто приведет к различным проблемам, по крайней мере, если он доступен без привилегий.

Как сказал Лутомирский: «Это не решает проблему. Если два разных пользователя запускают глупые программы, такие как gnupg, они просто истощат друг друга. Я вижу, что в настоящее время существуют две основные проблемы с /dev/random: он подвержен DoS (т. е. истощению ресурсов, вредоносному влиянию или чему-то подобному), и, поскольку никаких привилегий для его использования не требуется, он также подвержен злоупотреблениям. Gnupg — это неправильно, это полный коллапс. Если мы добавим новый непривилегированный интерфейс, который будут использовать gnupg и аналогичные программы, мы снова проиграем».

Мюллер отметил, что добавление getrandom() теперь позволит GnuPG использовать этот интерфейс, поскольку он обеспечит необходимую гарантию того, что пул был инициализирован. На основе дискуссий с разработчиком GnuPG Вернером Кохом (Werner Koch) Мюллер считает, что гарантия — это единственная причина, по которой GnuPG в настоящее время читает непосредственно из /dev/random. Но если есть непривилегированный интерфейс, который подвержен отказу в обслуживании (как на сегодня /dev/random), то по утверждению Лутомирского, он будет неправильно использоваться некоторыми приложениями.

Теодор Цао (Theodore Yue Tak Ts'o), разработчик подсистемы случайных чисел Linux, по-видимому, изменил свое мнение по поводу необходимости блокирующего пула. Он сказал, что удаление этого пула позволит эффективно избавиться от идеи, что Linux имеет настоящий генератор случайных чисел (TRNG): «это не является бессмыслицей, так как это именно то, что всегда делали *BSD".

Он также обеспокоен тем, что предоставление механизма TRNG будет просто служить в качестве приманки для разработчиков приложений и считает, что на самом деле, учитывая различные типы аппаратного обеспечения, поддерживаемого Linux, невозможно гарантировать TRNG в ядре. Проблему не решит даже возможность работы с оборудованием только на основе root-привилегий: «Разработчики прикладных программ указывают, чтобы их приложение в целях безопасности было установлено как root, потому только так вы можете получить доступ к «действительно хорошим» случайным числам".

Мюллер спросил, не отказался ли Цао от реализации блокирующего пула, которую он сам давно предложил. Цао ответил, что планирует взять патчи Лутомирского и активно возражает против добавления блокирующего интерфейса обратно в ядро.

«Ядро не может дать никаких гарантий относительно того, был ли охарактеризован noise source надлежащим образом. Единственное, что может получить разработчик GPG или OpenSSL — это смутное ощущение, что TRUERANDOM «лучше», а поскольку они хотят большей безопасности, то, несомненно, попытаются его использовать. В определенный момент он заблокируется, и когда какой-нибудь другой умный пользователь (возможно, специалист по выпуску дистрибутива) вставит его в init скрипт и системы перестанут работать, пользователям останется только жаловаться самому Линусу Торвальдсу».

Цао также выступает за то, чтобы предоставить криптографам и тем, кто действительно нуждается в TRNG, способ собирать свою собственную энтропию в пользовательском пространстве, чтобы использовать ее по своему усмотрению. Он говорит, что сбор энтропии — это не тот процесс, который может выполняться ядром на всевозможных поддерживаемых им аппаратных средствах, кроме того, само ядро не может оценить количество энтропии, обеспечиваемое различными источниками.

«Ядро не должно смешивать вместе различные noise source, и оно, конечно же, не должно пытаться утверждать, что знает, сколько бит энтропии оно получает, когда пытается играть в какую-то «дерганную игру энтропии» на простой до безобразия архитектуре CPU для пользовательских случаев IOT/Embedded, когда все рассинхронизировано с единственным мастер-генератором, когда нет никакой инструкции CPU для переупорядочения или переименования регистра и т. д.».

«Можно говорить о предоставлении инструментов, которые пытаются сделать эти расчеты, но такие вещи должны проводиться на оборудовании каждого пользователя, что для большинства пользователей дистрибутива просто непрактично. Если же это предназначено только для криптографов, то пусть будет сделано в их пользовательском пространстве. И давайте не будем упрощать GPG, OpenSSL и т. д., чтобы все говорили: «мы хотим «истинной случайности» и не согласны на меньшее». Можно говорить о том, как мы предоставляем интерфейсы криптографам, чтобы они могли получить необходимую информацию благодаря доступу к первичным noise sources, отделенным и поименованным, и, возможно, что каким-то образом noise source сможет аутентифицировать себя в библиотеке или приложении пользовательского пространства».


Имела место небольшая дискуссия о том, как может выглядеть такой интерфейс, ведь, например, для некоторых событий могут иметься последствия в плане безопасности. Цао отметил, что коды сканирования клавиатуры (то есть нажатия клавиш) смешиваются в пул как часть сбора энтропии: «Перенос этого в пользовательское пространство, даже через привилегированный системный вызов, было бы, по меньшей мере, неблагоразумно». Вполне возможно, что и другие тайминги событий могут создать какую-то утечку информации по побочным каналам.

Таким образом, возникает ощущение, что давняя проблема подсистемы случайных чисел Linux находится на пути к решению. Изменения, которые подсистема случайных чисел претерпела в последнее время, фактически приводили только к проблемам DoS в процессе ее использования. Теперь же появились эффективные способы получить наилучшие случайные числа, какие только может предоставить ядро. Если же TRNG все еще желателен для Linux, то этот недостаток нужно будет устранить в будущем, но, скорее всего, это не будет делаться внутри самого ядра.

Немного рекламы :)


Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас, оформив заказ или порекомендовав знакомым, облачные VPS для разработчиков от $4.99, уникальный аналог entry-level серверов, который был придуман нами для Вас: Вся правда о VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps от $19 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только у нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТВ от $199 в Нидерландах! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — от $99! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?