суббота, 4 августа 2012 г.

Проблема организации голосовых конференций в системах защищенной связи.


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

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

Политика сервиса Cryptia.com, состоит в том, что мы не стремимся хранить у себя конфиденциальные данные клиентов (или иметь к ней доступ). Все соединения между клиентами используют сквозное шифрование от клиента до клиента, без возможности расшифровки на сервере, а в 90% случаев они и проходят от клиента до клиента напрямую, минуя наши сервера.  Однако это с другой стороны делает невозможным организацию конференций на серверах, используя описанную выше технологию.

Описанное противоречие и есть причина того, что в сервисе Cryptia до сих пор не реализована функция конференции.

Для решения проблемы рассматривался вариант использования схемы согласования сеансового ключа по алгоритму Диффи-Хеллмана  для большого количества клиентов (> 2).  В этом случае сервер не расшифровывает голосовые пакеты и не может микшировать звук от разных клиентов, а только пересылает зашифрованные пакеты между клиентами. Клиент сам смешивает голосовой трафик на своем компьютере, но входящий трафик каждого участника конференции возрастает пропорционально количеству участников. Например, если в конференции участвуют 4 человека, то сервер будет пересылать на каждого участника пакеты от 3-х других и входящий трафик КАЖДОГО участника возрастет в 3 раза (относительно простого голосового сеанса).  Исходящий трафик останется без изменений. Возросший в 3 раза голосовой трафик может привести к тому, что один из клиентов может просто перестать работать.

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



Мы приняли компромиссное решение:
За функционирование конференции отвечает инициатор. Его клиентская программа выполняет роль  сервера конференции. Инициатор имеет защищенное соединение с каждым из участников  и расшифровывает пакеты, смешивает голосовые потоки и пересылает их другим.
Проблема трафика решается так: Трафик инициатора конференции возрастает пропорционально количеству участников, соответственно инициатор должен находиться в точке с хорошим Интернет каналом (не телефон с 3G). У остальных участников трафик не возрастает.  Проблема с обменом ключами в этом случае также решается – дополнительный обмен не требуется. Инициатор конференции расшифровывает все клиентские пакеты и пересылает их другим участникам. Разумеется, инициатор имеет возможность все видеть и, возможно, регистрировать, но он эту возможность имел и так (как и любой участник этой самой конференции).

Этот функционал будет включен в один из следующих релизов клиентской части продукта Cryptia.

OpenSSL и Qt.


OpenSSL сейчас является стандартом де-факто в области криптографии и используется повсеместно.

Во всех Linux, FreeBSD и Meego– при помощи библиотеки OpenSsl осуществляется все, что касается SSL соединений. В Mac OS X до 10.6 OpenSsl являлся единственным провайдером криптографических функций для SSL, а начиная с 10.7, появился новый провайдер, который, вероятно, использует только Apple. OpenSsl продолжает оставаться в MacOS X.  В Symbian OpenSsl присутствует во всех современных телефонах, однако, присутствует также и свой старый API для Symbian для поддержки старых приложений.

В процессе работы над клиентской и серверной частями сервиса cryptia.com было обнаружено, что в большинстве имеющихся на рынке unix based OS, собранный по умолчанию OpenSSL имеет умышленно вставленное ограничение на использование DSA ключей с длиной более 1024 бит.

Это обнаружено нами во ВСЕХ !!! имеющихся на рынке MacOS X, до 10.7.4. включительно, во всех Meego, в Symbian OS, во всех Android.
FreeBSD по умолчанию ставится тоже с пробитым OpenSSL, однако в портах лежит версия с официального сайта. Касательно репозитариев Linux: бывает по разному, но в большинстве дистрибутивов лежит версия с ослабленной защитой. В случае с сервисом Cryptia.com это проявляется в том, что клиентские сертификаты подписанные сервером (ключом DSA 2048 бит) не проходят верификацию в клиенте. Функция API EVP_VerifyFinal и EVP_SignFinal возвращает код ошибки («подпись не верна»).


У Вас на компьютере может стоять нормальный OpenSSL, однако при очередном обновлении OS из репозитария, в операционную систему, скорее всего, будет установлен  «правильный» OpenSSL и все программы начнут использовать его.



Как с этим бороться? «Таблетка».

Качать исходник OpenSSL с официального сайта openssl.org, который хостится в Германии и собирать его самому. Инструкция по сборке зависит от платформы, и для Desktop версии, как правило, не является проблемой.  Проблемой является избавиться в программе от зависимости Qt от OpenSsl в системе.

Замечания по грамотному использованию «Таблетки».

Qt библиотеки (OpenSSL использует только QtNetwork), как правило собираются с поддержкой динамической загрузки OpenSSL, хотя можно собрать и со статической линковкой OpenSSL.

Проблема в том, что в большинстве Linux дистрибутивов как-то собранные библиотеки Qt уже стоят (на Qt написана KDE). Также Qt уже установлена в последних телефонах с Symbian и Meego.  Требовать от пользователя поставить свой Qt или обновить его автоматически в программе установки дело очень рискованное – у пользователя могут «поломаться» уже установленные и работающие программы.

Почти во всех OS невозможно подгрузить в адресное пространство процесса две библиотеки с одинаковыми именами и одинаковым набором экспортируемых функций.

Если вы используете свою динамически загружаемую библиотеку OpenSsl, случайное обращение к QSslCertificates (Например, для того чтобы получить список корневых сертификатов встроенных в OS) приведет к тому что QtNetwork, попытается загрузить библиотеку OpenSsl, как правило из OS, а не вашу, потому что о вашей QtNetwork ничего не знает.

Вариант со статической линковкой своего Qt и openSsl  в программе, нравится не очень по следующим причинам:
  1. Как правило библиотеки Qt, по крайней мере в Linux, Symbian и Meego уже загружены каким-нибудь процессом в память и второй раз не загружаются, а вместо этого только выставляется отображение RO сегментов на память процесса и инициализация RW сегментов. Если статически слинковать весь Qt в программу, то программа «опухает» примерно на 10-15 MB, и запускается существенно дольше.
  2. В мобильных платформах ориентированных на Qt (Symbian, Meego (возможно BB10) ), тяжело пересобирать Qt статически.

По этой причине в клиентской программе Cryptia мы отказались от использования встроенной в Qt поддержки openssl. Для этого надо отказаться от использования всех классов начинающихся с QSsl (QSslSocket, QSslCertificate …). Все эти классы заменены своими. Для того чтобы случайно не «просочилось» где-нибудь в кусках старого кода использование этих классов, мы пересобрали у себя Qt c отключенной поддержкой OpenSsl. В этом случае компилятор будет ругаться при попытке использования в программе классов с QSsl  В своих классах мы используем вызовы своего OpenSSL, который статически линкуем к программе.

Таким образом, программа получается независимой от варианта сборки Qt, который она использует, а также от того, какой OpenSsl установлен у пользователя с одной стороны, а с другой – Qt все-таки динамически линкуется с программой и программа быстрее стартует на десктоп-платформах и просто работает на мобильных.


Ahtung. Пользователям программного обеспечения, которое использует библиотеку QCA.


QCA (Qt Cryptographic Architecture )  задумывался авторами, как кросс-платформенная библиотека надстройка над Qt, для функций шифрования.  Создавалась в те времена, когда в самой Qt функции шифрования не были встроены. 

Website: http://delta.affinix.com/qca/

После того как в самой Qt появились классы QSslSocket, QSslCertificates и.т.д.  разработка библиотеки была брошена авторами, однако многие продолжают ее использовать, например PSI. Кроме того последняя версия QCA (и плагина к ней для OpenSSL, датированного 2002 г. ) лежит во многих репозитариях Linux. Собственно всей криптография занимается OpenSSL, а QCA (с плагином для OpenSSL) выполняет роль прокладки между OpenSSL и Qt.  Криптографические функции в OpenSSL реализованы очень хорошо, однако требуют их грамотного использования, чем QCA похвастаться не может.

В частности OpenSSL требует грамотной инициализации пула случайных чисел (PRND)

А вот как инициализируется пул случайных чисел в QCA.

      srand(time(NULL));
      char buf[128];
      for(int n = 0; n < 128; ++n) buf[n] = rand();
      RAND_seed(buf, 128);

Как видно для инициализации используется «родная» функция rand() из библиотеки C, которая возвращает псевдослучайную последовательность чисел от 0 до 32767, а инициализируется генератор при помощи стандартной функции time, которая возвращает текущее время в виде количества секунд от 1 января 1970г. Фактически для взлома требуется небольшой перебор возможных значений времени в секундах от старта программы (порядка 12 бит.)