Руководство по стилю BoringSSL
BoringSSL обычно следует руководству по стилю Google C++ (https://google.github.io/styleguide/cppguide.html). Остальная часть этого документа описывает различия и уточнения на основе базового руководства.
Как производная от OpenSSL, BoringSSL содержит много устаревшего кода, который не соответствует этому руководству по стилю. В частности, в отношении открытого API необходимо соблюдать баланс согласованности внутри модуля с преимуществами данного правила. Отклонения от именования на уровне модулей должны соблюдаться, в то время как соглашения о целочисленных значениях и возвращаемых значениях имеют приоритет над согласованностью.
Модули из устаревшего стека ASN.1 и X.509 OpenSSL сохраняются для совместимости и остаются практически неизменными. Чтобы упростить импорт патчей из вышестоящего источника, они соответствуют новому стилю отступов OpenSSL. Для Emacs может быть полезен doc/openssl-c-indent.el
из OpenSSL.
Большая часть проекта написана на языке C, поэтому правила C++, специфичные для Google, не применяются. Поддержка функций C99 зависит от целевых платформ. Как правило, MSVC Chromium является наиболее ограничивающим.
Объявления переменных в середине функции или внутри цикла for
разрешены и предпочтительны, где это возможно. Обратите внимание, что общий шаблон очистки goto err
требует переноса некоторых объявлений переменных.
Комментарии должны быть // C99-style
для соответствия C++.
При объявлении типов указателей *
следует размещать рядом с именем переменной, а не с типом. Таким образом:
uint8_t *ptr;
а не
uint8_t* ptr;
Вместо malloc()
и free()
используйте оболочки OPENSSL_malloc()
и OPENSSL_free()
, а также свободно используйте стандартную функцию C assert()
.
Используйте следующие оболочки, найденные в crypto/internal.h
, вместо соответствующих функций стандартной библиотеки C. Они ведут себя так же, но избегают путаницы с неопределённым поведением.
OPENSSL_memchr
OPENSSL_memcmp
OPENSSL_memcpy
OPENSSL_memmove
OPENSSL_memset
Для новых констант предпочитайте перечисления, когда значения последовательны, и типизированные константы для флагов. Если вы добавляете значения к существующему набору #define
, продолжайте использовать #define
.
libssl изначально был написан на C, но постепенно переписывается на C++11. На момент написания большая часть стиля соответствует нашим соглашениям C, а не Google C++. Кроме того, libssl в Linux в настоящее время может не зависеть от среды выполнения C++. См. утилиты C++ в ssl/internal.h
для замены проблемных конструкций C++. Скрипт util/check_imported_libraries.go
можно использовать со сборкой разделяемой библиотеки, чтобы проверить, подходит ли новый конструктор.
Если вы не уверены, подберите код окружения. Расхождения между ним и стилем Google C++ будут устранены со временем.
Блоки с одним оператором не допускаются. Все условия и циклы должны использовать фигурные скобки:
if (foo) {
do_something();
}
а не:
if (foo)
do_something();
Предпочитайте использовать явно заданные целые числа там, где это уместно, а не общие C. Например, для представления байта используйте uint8_t
, а не unsigned char
. Аналогично представляйте двухбайтовое поле как uint16_t
, а не как unsigned short
.
Размеры представлены как size_t
.
В структуре, которая сохраняется в течение всего времени жизни SSL-соединения, если границы размера известны и это легко сделать, используйте меньший целочисленный тип, такой как uint8_t
. Это «бесплатная» оптимизация занимаемого места соединения для серверов. Не усложняйте код значительно ради этого, и всё ещё проверяйте границы при передаче в структуру и из неё. Это сужение не должно распространяться на локальные переменные и параметры функций.
При выполнении арифметических операций учитывайте условия переполнения.
За исключением платформенных API, не используйте ssize_t
. MSVC его не хватает, и предпочитайте внеполосное сигнализирование об ошибках для size_t
(см. Возвращаемые значения).
Следуйте соглашениям об именах Google в файлах C++. В файлах C используйте следующие соглашения об именах для обеспечения согласованности с существующими стилями OpenSSL и C:
Определите структуры с помощью typedef с именем TYPE_NAME
. Соответствующая структура должна называться struct type_name_st
.
Назовите общедоступные функции как MODULE_function_name
, если только функция не является конструктором или деструктором. Модуль
уже использует другую схему именования по причинам, связанным с наследием. Имя модуля должно быть именем типа, если функция является методом конкретного типа.
Некоторые типы выделяются в библиотеке, в то время как другие инициализируются в структуру, выделяемую вызывающей стороной, часто в стеке. Назовите эти функции TYPE_NAME_new
/TYPE_NAME_free
и TYPE_NAME_init
/TYPE_NAME_cleanup
соответственно. Все функции TYPE_NAME_free
должны ничего не делать при вводе NULL
.
Если переменная имеет длину значения указателя, она имеет суффикс _len
. Выходной параметр называется out
или имеет префикс out_
. Например:
uint8_t *out,
size_t *out_len,
const uint8_t *in,
size_t in_len.
Назовите публичные заголовки, такие как include/openssl/evp.h
, с защитными заголовками вроде OPENSSL_HEADER_EVP_H
. Назовите внутренние заголовки, например, crypto/ec/internal.h
с защитными заголовками, такими как OPENSSL_HEADER_EC_INTERNAL_H
.
Именуйте перечисления, например, enum unix_hacker_t
. Например:
enum should_free_handshake_buffer_t {
free_handshake_buffer,
dont_free_handshake_buffer
};
Возвращаемые значения
Поскольку даже malloc
может дать сбой в BoringSSL, подавляющее большинство функций будет иметь случай сбоя. Функции должны возвращать int
с единицей при успехе и нулём при ошибке. Не перегружайте возвращаемое значение для обозначения успеха/неудачи и вывода целого числа. Например:
OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out);
Если функции требуется больше, чем код результата true/false, определите перечисление вместо произвольного присвоения значения целым числам.
Если функция выводит указатель на объект при успешном выполнении и других выходных данных нет, верните указатель напрямую и NULL
при ошибке.
Параметры
Там, где это не ограничено устаревшим кодом, порядок параметров должен быть следующим:
Например:
/* CBB_add_asn устанавливает |*out_contents| в |CBB|, в который можно записать содержимое объекта ASN.1. Аргумент |tag| будет использоваться в качестве тега для объекта. Он возвращает единицу при успехе или ноль при ошибке. */
OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag);
Документация
Все публичные символы должны иметь комментарий документации в своём заголовочном файле. Стиль основан на стиле Go. Первое предложение начинается с имени символа, возможно, с префикса «A» или «An». Помимо первоначального упоминания символа, ссылки на другие символы или имена параметров должны быть заключены в вертикальные черты.
Документация должна быть краткой, но полностью описывать поведение функции. Обратите особое внимание на поведение успеха/неудачи и обязательства вызывающего объекта по времени жизни объекта. Если это жертвует краткостью, рассмотрите возможность упрощения поведения функции.
// EVP_DigestVerifyUpdate добавляет |len| байтов из |data| к данным, которые будут проверены |EVP_DigestVerifyFinal|. Возвращает единицу при успехе, иначе ноль.
OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len);
Явно упоминайте любые неожиданные крайние случаи или отклонения от общих шаблонов возвращаемых значений в устаревших функциях.
// RSA_private_encrypt шифрует |flen| байтов от |from| с помощью закрытого ключа в |rsa| и записывает зашифрованные данные в |to|. Буфер |to| должен иметь не менее |RSA_size| байт пространства. Возвращает количество записанных байтов или -1 при ошибке. Аргумент |padding| должен быть одним из значений |RSA_*_PADDING|. Если сомневаетесь, |RSA_PKCS1_PADDING| — наиболее распространённый вариант.
//
// ВНИМАНИЕ: эта функция опасна, поскольку нарушает обычную конвенцию о возвращаемом значении. Вместо этого используйте |RSA_sign_raw|.
OPENSSL_EXPORT int RSA_private_encrypt(int flen, const uint8_t *from, uint8_t *to, RSA *rsa, int padding);
Документируйте частные функции в их заголовке internal.h
или, если они статические, там, где они определены.
Логика сборки
BoringSSL используется многими проектами с различными инструментами сборки. Повторно реализовать и поддерживать...
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )