cmd.h 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. /*
  2. *******************************************************************************
  3. \file cmd.h
  4. \brief Command-line interface to Bee2
  5. \project bee2/cmd
  6. \created 2022.06.09
  7. \version 2024.06.14
  8. \copyright The Bee2 authors
  9. \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
  10. *******************************************************************************
  11. */
  12. #ifndef __BEE2_CMD_H
  13. #define __BEE2_CMD_H
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. #include <bee2/defs.h>
  18. #include <bee2/core/blob.h>
  19. #include <bee2/core/err.h>
  20. #include <bee2/core/tm.h>
  21. #include <bee2/crypto/btok.h>
  22. /*
  23. *******************************************************************************
  24. Блобы
  25. *******************************************************************************
  26. */
  27. /*! \brief Создание блоба */
  28. #define cmdBlobCreate(blob, size) \
  29. (((blob) = blobCreate(size)) ? ERR_OK : ERR_OUTOFMEMORY)
  30. /*! \brief Закрытие блоба */
  31. #define cmdBlobClose blobClose
  32. /*
  33. *******************************************************************************
  34. Регистрация команд
  35. *******************************************************************************
  36. */
  37. /*! \brief Главная функция команды */
  38. typedef int (*cmd_main_i)(
  39. int argc, /*!< [in] число параметров командной строки */
  40. char* argv[] /*!< [in] параметры командной строки */
  41. );
  42. /*! \brief Регистрация команды
  43. Регистрируется команда с именем name, описанием descr и главной
  44. функцией fn.
  45. \expect Строки name и descr -- статические, указатели на них остаются
  46. корректными на протяжении всего времени выполнения.
  47. \expect{ERR_BAD_FORMAT} 1 <= strLen(name) <= 8 && strLen(descr) <= 60.
  48. \return ERR_OK, если команда зарегистрирована, и код ошибки в противном
  49. случае.
  50. */
  51. err_t cmdReg(
  52. const char* name, /*!< [in] имя команды */
  53. const char* descr, /*!< [in] описание команды */
  54. cmd_main_i fn /*!< [in] главная функция команды */
  55. );
  56. /*
  57. *******************************************************************************
  58. Терминал
  59. *******************************************************************************
  60. */
  61. /*! \brief Нажата клавиша?
  62. Опрашивается теримнал и проверяется, что очередь нажатых клавиш не пуста.
  63. \return Признак нажатия.
  64. \remark Очередь очищается в том числе через вызовы cmdTermGetch().
  65. */
  66. bool_t cmdTermKbhit();
  67. /*! \brief Чтение символа
  68. Прочитывается символ, введенный в терминале.
  69. \return Прочитанный символ.
  70. \remark Прочитанный символ не экранируется.
  71. */
  72. int cmdTermGetch();
  73. /*
  74. *******************************************************************************
  75. ГСЧ
  76. В функции cmdKbRead() реализован клавиатурный источник энтропии. Реализация
  77. соответствует СТБ 34.101.27-2011 (Б.7):
  78. - при нажатии клавиш фиксируются значения высокоточного таймера (регистр TSC);
  79. - разность между значениями регистра сохраняется, если друг за другом нажаты
  80. две различные клавиши и интервал между нажатиями более 50 мс;
  81. - всего сохраняется 128 разностей;
  82. - собранные разности объединяются и хэшируются;
  83. - хэш-значение (32 октета) возвращается в качестве энтропийных данных.
  84. Дополнительно в cmdKbRead() проверяется, что интервал между нажатиями клавиш
  85. не превышает 5 секунд. При отсутствии активности со стороны пользователя
  86. сбор данных от источника будет прекращен.
  87. В функции cmdRngStart() проверяются требования СТБ 34.101.27-2020 уровня 1:
  88. наличие работоспособного физического источника энтропии или двух различных
  89. работоспособных источников. Если недостает одного источника, то задействуется
  90. клавиатурный.
  91. *******************************************************************************
  92. */
  93. /*! \brief Данные от клавиатурного источника энтропии
  94. Прочитываются даные data с клавиатурного источника энтропии.
  95. \return ERR_OK в случае успеха и код ошибки в противном случае.
  96. */
  97. err_t cmdRngKbRead(
  98. tm_ticks_t data[128] /*!< [out] данные */
  99. );
  100. /*! \brief Запуск ГСЧ
  101. Запускается штатный ГСЧ. При установке флага verbose запуск сопровождается
  102. экранным выводом.
  103. \return ERR_OK в случае успеха и код ошибки в противном случае.
  104. */
  105. err_t cmdRngStart(
  106. bool_t verbose /*!< [in] печатать подробности */
  107. );
  108. /*
  109. *******************************************************************************
  110. Дата
  111. *******************************************************************************
  112. */
  113. /*! \brief Разбор даты
  114. По строке str формата YYMMDD формируется дата date. При str == "000000" в
  115. date устанавливается текущая дата.
  116. \return ERR_OK, если строка имеет нужный формат и дата сформирована, и код
  117. ошибки в противном случае.
  118. */
  119. err_t cmdDateParse(
  120. octet date[6], /*!< [out] дата */
  121. const char* str /*!< [in] строка */
  122. );
  123. /*
  124. *******************************************************************************
  125. Печать
  126. *******************************************************************************
  127. */
  128. /*! \brief Печать памяти
  129. Печатается шестнадцатеричное представление буфера памяти [count]buf.
  130. \return ERR_OK в случае успеха и код ошибки в противном случае.
  131. */
  132. err_t cmdPrintMem(
  133. const void* buf, /*!< [in] буфер */
  134. size_t count /*!< [in] длина буфера в октетах */
  135. );
  136. /*! \brief Сокращенная печать памяти
  137. Печатается сокращенное шестнадцатеричное представление буфера памяти
  138. [count]buf:
  139. - если count > 14, то печатаются 12 первых октетов, многоточие,
  140. 2 последних октета и общее число октетов в скобках;
  141. - если count <= 14, то печатаются все октеты.
  142. \return ERR_OK в случае успеха и код ошибки в противном случае.
  143. */
  144. err_t cmdPrintMem2(
  145. const void* buf, /*!< [in] буфер */
  146. size_t count /*!< [in] длина буфера в октетах */
  147. );
  148. /*! \brief Печать даты
  149. Печатается дата date.
  150. \return ERR_OK в случае успеха и код ошибки в противном случае.
  151. */
  152. err_t cmdPrintDate(
  153. const octet date[6] /*!< [in] дата */
  154. );
  155. /*
  156. *******************************************************************************
  157. Файлы
  158. \remark Пара параметров (count, files) функций cmdFilesValXXX() соответствует
  159. паре (argc, argv) функции main(). Если заменить тип files на const char**,
  160. то возможны предупредеждения компилятора при переходе от argv к files
  161. (см. http://c-faq.com/ansi/constmismatch.html).
  162. *******************************************************************************
  163. */
  164. /*! \brief Размер файла
  165. Определяется размер файла с именем file.
  166. \return Размер файла или SIZE_MAX в случае ошибки.
  167. */
  168. size_t cmdFileSize(
  169. const char* file /*!< [in] имя файла */
  170. );
  171. /*! \brief Запись в файл
  172. Создается файл file и в него записывается буфер [count]buf.
  173. \return ERR_OK в случае успеха и код ошибки в противном случае.
  174. */
  175. err_t cmdFileWrite(
  176. const char* file, /*!< [in] файл */
  177. const void* buf, /*!< [in] буфер */
  178. size_t count /*!< [in] длина буфера */
  179. );
  180. /*! \brief Дозапись в файл
  181. В конец файла file дописывается буфер [count]buf.
  182. \return ERR_OK в случае успеха и код ошибки в противном случае.
  183. \remark Если file не существует, то он создается.
  184. */
  185. err_t cmdFileAppend(
  186. const char* file, /*!< [in] файл */
  187. const void* buf, /*!< [in] буфер */
  188. size_t count /*!< [in] длина буфера */
  189. );
  190. /*! \brief Дублирование содержимого файла
  191. В файле ifile пропускаются первые skip октетов, а следующие count октетов
  192. переписываются в файл ofile. При count == SIZE_MAX переписываются все
  193. октеты ifile вплоть до конца файла.
  194. \return ERR_OK в случае успеха и код ошибки в противном случае.
  195. */
  196. err_t cmdFileDup(
  197. const char* ofile, /*!< [in] выходной файл */
  198. const char* ifile, /*!< [in] входной файл */
  199. size_t skip, /*!< [in] число пропускаемых октетов */
  200. size_t count /*!< [in] число дублируемых октетов */
  201. );
  202. /*! \brief Чтение всего файла
  203. Буфер [?count]buf прочитывается из файла file. При ненулевом buf
  204. дополнительно проверяется, что переданная длина в точности совпадает
  205. с размером файла.
  206. \return ERR_OK в случае успеха и код ошибки в противном случае.
  207. */
  208. err_t cmdFileReadAll(
  209. void* buf, /*!< [in] буфер */
  210. size_t* count, /*!< [in] длина буфера */
  211. const char* file /*!< [in] файл */
  212. );
  213. /*! \brief Проверка отсутствия файлов
  214. Проверяется, что файлы списка [count]files отсутствуют и, таким образом,
  215. их можно создавать и записывать в них данные. Если некоторый файл все-таки
  216. присутствует, то предлагается его перезаписать. Разрешение на перезапись
  217. приравнивается к отсутствию файла.
  218. \return ERR_OK в случае успеха и код ошибки в противном случае.
  219. */
  220. err_t cmdFileValNotExist(
  221. int count, /*!< [in] число файлов */
  222. char* files[] /*!< [in] список имен файлов */
  223. );
  224. /*! \brief Проверка наличия файлов
  225. Проверяется существование файлов списка [count]files.
  226. \return ERR_OK в случае успеха и код ошибки в противном случае.
  227. */
  228. err_t cmdFileValExist(
  229. int count, /*!< [in] число файлов */
  230. char* files[] /*!< [in] список имен файлов */
  231. );
  232. /*! \brief Проверка совпадения файлов
  233. Проверяется, что имена file1 и file2 соответствуют одному и тому же файлу.
  234. \return Признак успеха.
  235. \remark Корректность имен не проверяется.
  236. */
  237. bool_t cmdFileAreSame(
  238. const char* file1, /*!< [in] первый файл */
  239. const char* file2 /*!< [in] второй файл */
  240. );
  241. /*
  242. *******************************************************************************
  243. Командная строка
  244. *******************************************************************************
  245. */
  246. /*! \brief Создание списка аргументов
  247. По командной строке args строится список аргументов [argc]argv.
  248. \pre Указатели argc, argv и строка args корректны.
  249. \return ERR_OK в случае успеха и код ошибки в противном случае.
  250. \remark Аргументами считаются фрагменты args, разделенные пробелами.
  251. Фрагмент, окаймленный кавычками, считаются единым аргументом, даже если
  252. внутри него содержатся пробелы.
  253. \remark Детали:
  254. https://docs.microsoft.com/cpp/c-language/parsing-c-command-line-arguments
  255. */
  256. err_t cmdArgCreate(
  257. int* argc, /*!< [out] число аргументов */
  258. char*** argv, /*!< [out] список аргументов */
  259. const char* args /*!< [in] командная строка */
  260. );
  261. /*! \brief Закрытие списка аргументов
  262. Закрывается список аргументов argv, созданный в функции cmdArgCreate().
  263. \pre cmdArgCreate() < cmdArgClose().
  264. */
  265. void cmdArgClose(
  266. char** argv /*!< [in] список аргументов */
  267. );
  268. /*
  269. *******************************************************************************
  270. Управление паролями
  271. Пароль представляется собой стандартную C-строку (с завершающим нулем).
  272. Пароль размещается в блобе, который создается внутри функций cmdPwdGen(),
  273. cmdPwdRead(). Схема возврата [pwd_len?]pwd не используется, потому что
  274. в некоторых случаях (например, при вводе пароля с консоли) важно, чтобы пароль
  275. можно было возвратить за один вызов функции. За закрытие блоба отвечает
  276. вызывающая программа.
  277. Пароль задается в командной строке в стиле OpenSSL:
  278. - обычно после аргумента "-pass" / "-passin" / "-passout" / ...;
  279. - имеется несколько схем задания пароля;
  280. - схема pass предназначена для задания пароля прямо в командной строке:
  281. "-pass pass:password";
  282. - схема env предназначена для задания пароля через переменную окружения:
  283. "-pass env:ENV_VAR";
  284. - схема share предназначена для задания пароля с помощью методов
  285. разделения секрета в соответствии с правилами СТБ 34.101.78:
  286. "-pass share:\"share_descr\"".
  287. В схеме share параметры share_args, которые описывают настройку разделения
  288. секрета, имеют следующий синтаксис:
  289. \code
  290. [-t<nn>] [-l<mmm>] -pass <schema> <share1> <share2> ....
  291. \endcode
  292. Здесь:
  293. - <nn> -- порог числа частичных секретов (2 <= n <= 16, 2 по умолчанию);
  294. - <mmm> -- уровень стойкости (128, 192 или 256, 256 по умолчанию);
  295. - <schema> --- описание пароля защиты файлов с частичными секретами;
  296. - <share1>, <share2>,... -- файлы с частичными секретами (их число должно быть
  297. не меньше порога и не больше 16).
  298. \todo Поддержать опции "file:pathname", "fd:number" и "stdin", реализованные
  299. в OpenSSL
  300. (https://www.openssl.org/docs/manmaster/man1/openssl-passphrase-options.html).
  301. \todo Поддержать правила кодирования паролей, реализованные в OpenSSL
  302. (https://www.openssl.org/docs/manmaster/man7/passphrase-encoding.html).
  303. *******************************************************************************
  304. */
  305. /*! \brief Пароль */
  306. typedef char* cmd_pwd_t;
  307. /*! \brief Создание пароля
  308. Создается блоб для хранения пароля максимальной длины size.
  309. \return Дескриптор блоба. Нулевой дескриптор возвращается
  310. при нехватке памяти.
  311. \remark При создании блоба все его октеты обнуляются.
  312. */
  313. cmd_pwd_t cmdPwdCreate(
  314. size_t size /*!< [in] максимальная длина */
  315. );
  316. /*! \brief Корректный пароль?
  317. Проверяется корректность пароля pwd.
  318. \return Признак корректности.
  319. \remark Пароль корректен, если он хранится в корректном непустом блобе,
  320. который завершается нулевым октетом.
  321. */
  322. bool_t cmdPwdIsValid(
  323. const cmd_pwd_t pwd /*!< [in] корректный блоб */
  324. );
  325. /*! \brief Закрытие пароля
  326. Выполняется очистка и освобождение блоба пароля pwd.
  327. */
  328. void cmdPwdClose(
  329. cmd_pwd_t pwd /*!< [in] пароль */
  330. );
  331. /*! \brief Длина пароля */
  332. #define cmdPwdLen strLen
  333. /*! \brief Генерация пароля
  334. По инструкциям во фрагменте cmdline командной строки генерируется пароль pwd.
  335. \expect{ERR_NOT_IMPLEMENTED} Используется парольная схема share.
  336. \return ERR_OK, если пароль успешно сгенерирован, и код ошибки в противном
  337. случае.
  338. \remark За закрытие пароля отвечает вызывающая программа.
  339. */
  340. err_t cmdPwdGen(
  341. cmd_pwd_t* pwd, /*!< [out] пароль */
  342. const char* cmdline /*!< [in] фрагмент командной строки */
  343. );
  344. /*! \brief Определение пароля
  345. По инструкциям во фрагменте cmdline командной строки определяется
  346. ранее построенный пароль pwd.
  347. \return ERR_OK, если пароль успешно определен, и код ошибки в противном
  348. случае.
  349. \remark За закрытие пароля отвечает вызывающая программа.
  350. */
  351. err_t cmdPwdRead(
  352. cmd_pwd_t* pwd, /*!< [out] пароль */
  353. const char* cmdline /*!< [in] фрагмент командной строки */
  354. );
  355. /*
  356. *******************************************************************************
  357. Управление личными ключами СТБ 34.101.45 (bign)
  358. Личные ключи хранятся в контейнерах, защищенных на паролях по схеме
  359. СТБ 34.101.78 (bpki).
  360. \expect Личный ключ связан со стандартными параметрами СТБ 34.101.45 того или
  361. иного уровня стойкости: bign-curve256v1, bign-curve384v1 или bign-curve512v1.
  362. *******************************************************************************
  363. */
  364. /*! \brief Запись личного ключа в контейнер
  365. Личный ключ [privkey_len]privkey записывается в защищенный файл-контейнер
  366. file. Защита устанавливается на пароле pwd.
  367. \return ERR_OK, если ключ успешно записан, и код ошибки в противном случае.
  368. */
  369. err_t cmdPrivkeyWrite(
  370. const octet privkey[], /*!< [in] личный ключ */
  371. size_t privkey_len, /*!< [in] длина личного ключа */
  372. const char* file, /*!< [in] имя контейнера */
  373. const cmd_pwd_t pwd /*!< [in] пароль защиты */
  374. );
  375. /*! \brief Чтение личного ключа из контейнера
  376. Личный ключ [privkey_len?]privkey читается из защищенного файла-контейнера
  377. file. Защита снимается на пароле pwd.
  378. \pre Если адрес privkey_len ненулевой, то по этому адресу передается
  379. одно из следующих значений: 0, 32, 48, 64. Нулевое значение соответствует
  380. стандартной логике [privkey_len?]. Ненулевые значения соответствуют логике
  381. [?privkey_len], то есть задают требуемую длину ключа.
  382. \expect{ERR_BAD_FORMAT} Если privkey_len != 0 и *privkey_len != 0,
  383. то контейнер file содержит ключ из *privkey_len октетов.
  384. \return ERR_OK, если ключ успешно прочитан, и код ошибки в противном случае.
  385. */
  386. err_t cmdPrivkeyRead(
  387. octet privkey[], /*!< [out] личный ключ */
  388. size_t* privkey_len, /*!< [out] длина личного ключа */
  389. const char* file, /*!< [in] имя контейнера */
  390. const cmd_pwd_t pwd /*!< [in] пароль защиты */
  391. );
  392. /*
  393. *******************************************************************************
  394. CV-сертификаты
  395. *******************************************************************************
  396. */
  397. /*! \brief Печать CV-сертификата
  398. Печатается область CV-сертификата cvc, заданная строкой scope:
  399. - если scope != 0, то печатается поле с именем scope ("authority",
  400. "holder", "from", "until", "eid", "esign" или "pubkey");
  401. - если scope == 0, то печатаются все поля сертификата.
  402. \return ERR_OK, если печать успешно выполнена, и код ошибки
  403. в противном случае.
  404. */
  405. err_t cmdCVCPrint(
  406. const btok_cvc_t* cvc, /*!< [in] сертификат */
  407. const char* scope /*!< [in] область печати */
  408. );
  409. /*
  410. *******************************************************************************
  411. Коллекции и цепочки сертификатов
  412. Коллекция сертификатов --- это конкатенация нескольких сертификатов.
  413. Цепочка сертификатов -- это коллекция, в которой каждый следующий сертификат
  414. выпущен владельцем предыдущего.
  415. *******************************************************************************
  416. */
  417. /*! \brief Создание коллекции сертификатов
  418. По строке descr, в которой через пробел перечисляются имена файлов
  419. сертификатов, создается коллекция [?cert_len]certs.
  420. \return ERR_OK, если коллекция создана, и код ошибки в противном случае.
  421. */
  422. err_t cmdCVCsCreate(
  423. octet* certs, /*!< [out] коллекция сертификатов */
  424. size_t* count, /*!< [out] длина коллекции (в октетах) */
  425. const char* descr /*!< [in] описание коллекции */
  426. );
  427. /*! \brief Число сертификатов в коллекции
  428. Определяется число count сертификатов в коллекции [certs_len]certs.
  429. \return ERR_OK, если число сертификатов определено, и код ошибки
  430. в противном случае.
  431. */
  432. err_t cmdCVCsCount(
  433. size_t* count, /*!< [out] число сертификатов */
  434. const octet* certs, /*!< [in] коллекция сертификатов */
  435. size_t certs_len /*!< [in] длина коллекции */
  436. );
  437. /*! \brief Получение сертификата коллекции
  438. В коллекции [certs_len]certs определяется сертификат с номером num.
  439. Его смещение в коллекции возвращается по адресу offset, а длина --
  440. по адресу cert_len.
  441. \return ERR_OK, если сертификат получен, и код ошибки в противном случае.
  442. \remark Любой из адресов offset, cert_len может быть нулевым, и тогда
  443. данные по этому адресу не возвращаются.
  444. */
  445. err_t cmdCVCsGet(
  446. size_t* offset, /*!< [out] смещение сертификата */
  447. size_t* cert_len, /*!< [out] длина сертификата */
  448. const octet* certs, /*!< [in] коллекция сертификатов */
  449. size_t certs_len, /*!< [in] длина коллекции */
  450. size_t num /*!< [in] номер сертификата */
  451. );
  452. /*! \brief Получение последнего сертификата коллекции
  453. В коллекции [certs_len]certs определяется последний сертификат.
  454. Его смещение в коллекции возвращается по адресу offset, а длина --
  455. по адресу cert_len.
  456. \return ERR_OK, если сертификат получен, и код ошибки в противном случае.
  457. \remark Любой из адресов offset, cert_len может быть нулевым, и тогда
  458. данные по этому адресу не возвращаются.
  459. */
  460. err_t cmdCVCsGetLast(
  461. size_t* offset, /*!< [out] смещение сертификата */
  462. size_t* cert_len, /*!< [out] длина сертификата */
  463. const octet* certs, /*!< [in] коллекция сертификатов */
  464. size_t certs_len /*!< [in] длина коллекции */
  465. );
  466. /*! \brief Поиск сертификата в коллекции
  467. В коллекции [certs_len]certs ведется поиск сертификата [cert_len]cert.
  468. Его смещение в коллекции возвращается по адресу offset.
  469. \return ERR_OK, если сертификат найден, и код ошибки в противном случае.
  470. \remark Адрес offset может быть нулевым, и тогда данные по этому адресу
  471. не возвращаются.
  472. */
  473. err_t cmdCVCsFind(
  474. size_t* offset, /*!< [out] смещение сертификата */
  475. const octet* certs, /*!< [in] коллекция сертификатов */
  476. size_t certs_len, /*!< [in] длина коллекции */
  477. const octet* cert, /*!< [in] cертификат */
  478. size_t cert_len /*!< [in] длина сертификата */
  479. );
  480. /*! \brief Проверка коллекции сертификатов
  481. Проверяется корректность сертификатов коллекции [certs_len]certs.
  482. \return ERR_OK, если проверка прошла успешно, и код ошибки
  483. в противном случае.
  484. */
  485. err_t cmdCVCsCheck(
  486. const octet* certs, /*!< [in] коллекция сертификатов */
  487. size_t certs_len /*!< [in] длина коллекции */
  488. );
  489. /*! \brief Проверка цепочки сертификатов
  490. Проверяется корректность цепочки сертификатов [certs_len]certs
  491. на дату date.
  492. \return ERR_OK, если проверка прошла успешно, и код ошибки
  493. в противном случае.
  494. \remakr Дата date должна попадать в срок действия последнего сертификата
  495. цепочки.
  496. \remark Указатель date может быть нулевым или массив date может быть
  497. заполнен нулями, и тогда дата игнорируется.
  498. */
  499. err_t cmdCVCsVal(
  500. const octet* certs, /*!< [in] цепочка сертификатов */
  501. size_t certs_len, /*!< [in] длина цепочки (в октетах) */
  502. const octet date[6] /*!< [in] дата проверки */
  503. );
  504. /*! \brief Печать коллекции сертификатов
  505. Печатается коллекция сертификатов [certs_len]certs.
  506. \return ERR_OK, если печать успешно выполнена, и код ошибки
  507. в противном случае.
  508. */
  509. err_t cmdCVCsPrint(
  510. const octet* certs, /*!< [in] коллекция сертификатов */
  511. size_t certs_len /*!< [in] длина коллекции */
  512. );
  513. /*
  514. *******************************************************************************
  515. ЭЦП
  516. ЭЦП может сопровождаться (обратной) цепочкой CV-сертификатов. Первым в цепочке
  517. идет сертификат подписанта. Каждый следующий сертификат -- это сертификат
  518. удостоверяющего центра, выпустившего предыдущий сертификат.
  519. ЭЦП может сопровождаться датой выработки подписи. Дата задается 6 октетами
  520. по схеме YYMMDD, которая используется в CV-сертификатах (см. btok.h).
  521. Если все октеты нулевые, то значит дата не указана.
  522. Цепочка сертификатов и дата подписываются вместе с содержимым целевого файла.
  523. При этом смена сертификата подписанта в цепочке сделает подпись
  524. недействительной, даже если открытый ключ будет повторен в двух сертификатах
  525. (см. RFC5035: описание угроз, описание атрибута SigningCertificateV2).
  526. Формат ЭЦП:
  527. \code
  528. Signature ::= SEQUENCE
  529. {
  530. certs SEQUENCE OF CVCertificate,
  531. sig OCTET STRING(SIZE(48|72|96)),
  532. date CVDate OPTIONAL
  533. }
  534. CVDate ::= OCTET STRING(SIZE(6))
  535. \endcode
  536. Для управления форматом предусмотрена структура cmd_sig_t. В поле certs этой
  537. структуры cmd_sig_t размещается цепочка сертификатов. Сертификаты цепочки
  538. записываются последовательно друг за другом без разделителей. Сертификаты
  539. закодированы по правилам АСН.1, их длины однозначно определяются в ходе
  540. декодирования. Дата (date) и подпись (sig) также кодируются по правилам
  541. АСН.1.
  542. DER-код структуры Signature (строка октетов) переворачивается. За счет
  543. переворота DER-код однозначно декодируется даже будучи записанным в конец
  544. файла произвольного размера. В частности, подпись может быть присоединена
  545. к подписывемому файлу. В этом случае при проверке подписи она исключается
  546. из контролируемого содержимого файла.
  547. *******************************************************************************
  548. */
  549. /*! \brief Подпись и сопровождающие сертификаты */
  550. typedef struct {
  551. octet sig[96]; /*!< подпись */
  552. size_t sig_len; /*!< длина подписи в октетах */
  553. octet certs[1460]; /*!< цепочка сертификатов */
  554. size_t certs_len; /*!< cуммарная длина сертификатов */
  555. octet date[6]; /*!< дата выработки подписи */
  556. } cmd_sig_t;
  557. /*! \brief Подпись файла
  558. Содержимое файла file подписывается на личном ключе [privkey_len]privkey
  559. с указанием date в качестве даты подписания. При передаче нулевого буфера
  560. date дата подписания не указывается.Подпись сохраняется в файле sig_file
  561. вместе с сертификатами цепочки certs. Цепочка certs может быть пустой.
  562. В качестве файла подписи можно указать подписываемый файл, и тогда подпись
  563. записывается в его конец.
  564. \expect{ERR_BAD_KEYPAIR} Если цепочка certs непуста, то ее первый
  565. сертификат соответствует privkey.
  566. \expect{ERR_BAD_CERT} Если цепочка certs непуста, то каждый ее сертификат,
  567. начиная со второго, -- это сертификат удостоверяющего центра, выпустившего
  568. предыдущий сертификат.
  569. \expect{ERR_BAD_DATE} Если дата подписания date указана, то она корректна.
  570. \expect{ERR_OUTOFRANGE} Если дата подписания date указана, то все
  571. сертификаты цепочки certs действительны на эту дату.
  572. \return ERR_OK, если файл успешно подписан, и код ошибки в противном
  573. случае.
  574. \remark В списке certs указываются имена файлов сертификатов. Имена
  575. разделяются пробелами. Имена могут окаймляться кавычками.
  576. \remark Файлы file и sig_file могут совпадать, и тогда подпись
  577. присоединяется к подписываемому файлу.
  578. */
  579. err_t cmdSigSign(
  580. const char* sig_file, /*!< [in] файл подписи */
  581. const char* file, /*!< [in] подписываемый файл */
  582. const char* certs, /*!< [in] цепочка сертификатов */
  583. const octet date[6], /*!< [in] дата подписания */
  584. const octet privkey[], /*!< [in] личный ключ */
  585. size_t privkey_len /*!< [in] длина личного ключа */
  586. );
  587. /*! \brief Чтение подписи
  588. Из файла sig_file прочитывается подпись sig. При ненулевом sig_len по этому
  589. адресу возвращается длина DER-кода подписи.
  590. \return ERR_OK, если подпись успешно прочитана, и код ошибки в противном
  591. случае.
  592. */
  593. err_t cmdSigRead(
  594. cmd_sig_t* sig, /*!< [out] подпись */
  595. size_t* sig_len, /*!< [out] длина DER-кода подписи */
  596. const char* sig_file /*!< [in] файл с подписью */
  597. );
  598. /*! \brief Проверка подписи файла на открытом ключе
  599. Подпись содержимого файла file, размещенная в sig_file, проверяется
  600. на открытом ключе [pubkey_len]pubkey. В качестве файла подписи может
  601. указывать подписываемый файл, и тогда подпись прочитывается из его конца
  602. и исключается из содержимого файла при проверке.
  603. \expect{ERR_BAD_KEYPAIR} Если подпись сопровождается цепочкой сертификатов,
  604. то ее первый сертификат соответствует pubkey.
  605. \expect{ERR_BAD_CERT} Если подпись сопровождается цепочкой сертификатов,
  606. то каждый ее сертификат, начиная со второго, -- это сертификат
  607. удостоверяющего центра, выпустившего предыдущий сертификат.
  608. \expect{ERR_BAD_DATE} Если подпись сопровождается датой подписания,
  609. то эта дата корректна.
  610. \expect{ERR_OUTOFRANGE} Если подпись сопровождается датой подписания, то все
  611. сертификаты вложеннной цепочки действительны на эту дату.
  612. \expect{ERR_BAD_FORMAT} Если подпись размещается в отдельном файле, то этот
  613. файл содержит исключительно подпись.
  614. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  615. */
  616. err_t cmdSigVerify(
  617. const char* file, /*!< [in] подписанный файл */
  618. const char* sig_file, /*!< [in] файл подписи */
  619. const octet pubkey[], /*!< [in] открытый ключ */
  620. size_t pubkey_len /*!< [in] длина открытого ключа */
  621. );
  622. /*! \brief Проверка подписи файла на доверенном сертификате
  623. Подпись содержимого файла file, размещенная в sig_file, проверяется
  624. на доверенном сертификате [anchor_len]anchor. Проверка будет завершена
  625. успешно, если подпись сопровождается цепочкой сертификатов и признается
  626. корректной на первом сертификате цепочки. В качестве файла подписи может
  627. указывать подписываемый файл, и тогда подпись прочитывается из его конца
  628. и исключается из содержимого файла при проверке.
  629. \expect{ERR_NO_TRUST} Один из сертификатов цепочки совпадает с anchor.
  630. \expect{ERR_BAD_CERT} Каждый сертификат цепочки, начиная со второго, --
  631. это сертификат удостоверяющего центра, выпустившего предыдущий сертификат.
  632. \expect{ERR_BAD_DATE} Если подпись сопровождается датой подписания,
  633. то эта дата корректна.
  634. \expect{ERR_OUTOFRANGE} Если подпись сопровождается датой подписания, то все
  635. сертификаты вложеннной цепочки действительны на эту дату.
  636. \expect{ERR_BAD_FORMAT} Если подпись размещается в отдельном файле, то этот
  637. файл содержит исключительно подпись.
  638. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  639. */
  640. err_t cmdSigVerify2(
  641. const char* file, /*!< [in] подписанный файл */
  642. const char* sig_file, /*!< [in] файл подписи */
  643. const octet anchor[], /*!< [in] доверенный сертификат */
  644. size_t anchor_len /*!< [in] длина anchor */
  645. );
  646. /*! \brief Самопроверка подписи на открытом ключе
  647. Подпись исполнимого файла, в котором вызывается данная функция,
  648. прочитывается из конца этого же файла и проверяется на открытом ключе
  649. [pubkey_len]pubkey через обращение к cmdSigVerify(pubkey, pubkey_len).
  650. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  651. */
  652. err_t cmdSigSelfVerify(
  653. const octet pubkey[], /*!< [in] открытый ключ */
  654. size_t pubkey_len /*!< [in] длина открытого ключа */
  655. );
  656. /*! \brief Самопроверка подписи на доверенном сертификате
  657. Подпись исполнимого файла, в котором вызывается данная функция,
  658. прочитывается из конца этого же файла и проверяется на доверенном
  659. сертификате [anchor_len]anchor через обращение к
  660. cmdSigVerify2(anchor, anchor_len).
  661. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  662. */
  663. err_t cmdSigSelfVerify2(
  664. const octet anchor[], /*!< [in] доверенный сертификат */
  665. size_t anchor_len /*!< [in] длина anchor */
  666. );
  667. /*! \brief Извлечение объекта из подписи
  668. Из подписи, размещенной в файле sig_file, извлекается и сохраняется в файле
  669. file объект, описанный строкой scope:
  670. - n-й сертификат, если scope == "cert<n>" (нумерация от нуля, сертификат
  671. подписанта идет последним);
  672. - подписанное содержимое, если scope == "body";
  673. - собственно подпись, если scope == "sig".
  674. \return ERR_OK, если объект успешно извлечен, и код ошибки в противном
  675. случае.
  676. */
  677. err_t cmdSigExtr(
  678. const char* obj_file, /*!< [in] файл c объектом */
  679. const char* sig_file, /*!< [in] файл подписи */
  680. const char* scope /*!< [in] область */
  681. );
  682. /*! \brief Печать подписи
  683. Печатается область подписи, размещенной в конце файла sig_file. Область
  684. задается строкой scope:
  685. - если scope != 0, то печатается поле с именем scope ("certnum", "date");
  686. - если scope == 0, то печатается вся подпись.
  687. \return ERR_OK, если печать успешно выполнена, и код ошибки
  688. в противном случае.
  689. */
  690. err_t cmdSigPrint(
  691. const char* sig_file, /*!< [in] файл подписи */
  692. const char* scope /*!< [in] область печати */
  693. );
  694. #ifdef __cplusplus
  695. } /* extern "C" */
  696. #endif
  697. #endif /* __BEE2_CMD_H */