cmd.h 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. /*
  2. *******************************************************************************
  3. \file cmd.h
  4. \brief Command-line interface to Bee2
  5. \project bee2/cmd
  6. \created 2022.06.09
  7. \version 2023.12.17
  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. - схема share предлназначена для задания пароля с помощью методов
  283. разделения секрета в соответствии с правилами СТБ 34.101.78:
  284. "-pass share:\"share_descr\"";
  285. В последнем случае параметры share_args, которые описывают настройку разделения
  286. секрета, имеют следующий синтаксис:
  287. \code
  288. [-t<nn>] [-l<mmm>] -pass <schema> <share1> <share2> ....
  289. \endcode
  290. Здесь:
  291. - <nn> -- порог числа частичных секретов (2 <= n <= 16, 2 по умолчанию);
  292. - <mmm> -- уровень стойкости (128, 192 или 256, 256 по умолчанию);
  293. - <schema> --- описание пароля защиты файлов с частичными секретами;
  294. - <share1>, <share2>,... -- файлы с частичными секретами (их число должно быть
  295. не меньше порога и не больше 16).
  296. \todo Поддержать опции "env:var", "file:pathname", "fd:number" и "stdin",
  297. реализованные в OpenSSL
  298. (https://www.openssl.org/docs/manmaster/man1/openssl-passphrase-options.html).
  299. \todo Поддержать правила кодирования паролей, реализованные в OpenSSL
  300. (https://www.openssl.org/docs/manmaster/man7/passphrase-encoding.html).
  301. *******************************************************************************
  302. */
  303. /*! \brief Пароль */
  304. typedef char* cmd_pwd_t;
  305. /*! \brief Создание пароля
  306. Создается блоб для хранения пароля максимальной длины size.
  307. \return Дескриптор блоба. Нулевой дескриптор возвращается
  308. при нехватке памяти.
  309. \remark При создании блоба все его октеты обнуляются.
  310. */
  311. cmd_pwd_t cmdPwdCreate(
  312. size_t size /*!< [in] максимальная длина */
  313. );
  314. /*! \brief Корректный пароль?
  315. Проверяется корректность пароля pwd.
  316. \return Признак корректности.
  317. \remark Пароль корректен, если он хранится в корректном непустом блобе,
  318. который завершается нулевым октетом.
  319. */
  320. bool_t cmdPwdIsValid(
  321. const cmd_pwd_t pwd /*!< [in] корректный блоб */
  322. );
  323. /*! \brief Закрытие пароля
  324. Выполняется очистка и освобождение блоба пароля pwd.
  325. */
  326. void cmdPwdClose(
  327. cmd_pwd_t pwd /*!< [in] пароль */
  328. );
  329. /*! \brief Длина пароля */
  330. #define cmdPwdLen strLen
  331. /*! \brief Построение пароля
  332. По инструкциям во фрагменте cmdline командной строки строится пароль pwd.
  333. \pre При использовании некоторых опций, в частности "share", должен быть
  334. проинициализирован штатный ГСЧ: rngIsValid() == TRUE.
  335. \return ERR_OK, если пароль успешно построен, и код ошибки
  336. в противном случае.
  337. \remark За закрытие пароля отвечает вызывающая программа.
  338. */
  339. err_t cmdPwdGen(
  340. cmd_pwd_t* pwd, /*!< [out] пароль */
  341. const char* cmdline /*!< [in] фрагмент командной строки */
  342. );
  343. /*! \brief Определение пароля
  344. По инструкциям во фрагменте cmdline командной строки определяется
  345. ранее построенный пароль pwd.
  346. \return ERR_OK, если пароль успешно определен, и код ошибки в противном
  347. случае.
  348. \remark За закрытие пароля отвечает вызывающая программа.
  349. */
  350. err_t cmdPwdRead(
  351. cmd_pwd_t* pwd, /*!< [out] пароль */
  352. const char* cmdline /*!< [in] фрагмент командной строки */
  353. );
  354. /*
  355. *******************************************************************************
  356. Управление личными ключами СТБ 34.101.45 (bign)
  357. Личные ключи хранятся в контейнерах, защищенных на паролях по схеме
  358. СТБ 34.101.78 (bpki).
  359. \expect Личный ключ связан со стандартными параметрами СТБ 34.101.45 того или
  360. иного уровня стойкости: bign-curve256v1, bign-curve384v1 или bign-curve512v1.
  361. *******************************************************************************
  362. */
  363. /*! \brief Запись личного ключа в контейнер
  364. Личный ключ [privkey_len]privkey записывается в защищенный файл-контейнер
  365. file. Защита устанавливается на пароле pwd.
  366. \return ERR_OK, если ключ успешно записан, и код ошибки в противном случае.
  367. */
  368. err_t cmdPrivkeyWrite(
  369. const octet privkey[], /*!< [in] личный ключ */
  370. size_t privkey_len, /*!< [in] длина личного ключа */
  371. const char* file, /*!< [in] имя контейнера */
  372. const cmd_pwd_t pwd /*!< [in] пароль защиты */
  373. );
  374. /*! \brief Чтение личного ключа из контейнера
  375. Личный ключ [privkey_len?]privkey читается из защищенного файла-контейнера
  376. file. Защита снимается на пароле pwd.
  377. \pre Если адрес privkey_len ненулевой, то по этому адресу передается
  378. одно из следующих значений: 0, 32, 48, 64. Нулевое значение соответствует
  379. стандартной логике [privkey_len?]. Ненулевые значения соответствуют логике
  380. [?privkey_len], то есть задают требуемую длину ключа.
  381. \expect{ERR_BAD_FORMAT} Если privkey_len != 0 и *privkey_len != 0,
  382. то контейнер file содержит ключ из *privkey_len октетов.
  383. \return ERR_OK, если ключ успешно прочитан, и код ошибки в противном случае.
  384. */
  385. err_t cmdPrivkeyRead(
  386. octet privkey[], /*!< [out] личный ключ */
  387. size_t* privkey_len, /*!< [out] длина личного ключа */
  388. const char* file, /*!< [in] имя контейнера */
  389. const cmd_pwd_t pwd /*!< [in] пароль защиты */
  390. );
  391. /*
  392. *******************************************************************************
  393. CV-сертификаты
  394. *******************************************************************************
  395. */
  396. /*! \brief Печать CV-сертификата
  397. Печатается область CV-сертификата cvc, заданная строкой scope:
  398. - если scope != 0, то печатается поле с именем scope ("authority",
  399. "holder", "from", "until", "eid", "esign" или "pubkey");
  400. - если scope == 0, то печатаются все поля сертификата.
  401. \return ERR_OK, если печать успешно выполнена, и код ошибки
  402. в противном случае.
  403. */
  404. err_t cmdCVCPrint(
  405. const btok_cvc_t* cvc, /*!< [in] сертификат */
  406. const char* scope /*!< [in] область печати */
  407. );
  408. /*
  409. *******************************************************************************
  410. Коллекции и цепочки сертификатов
  411. Коллекция сертификатов --- это конкатенация нескольких сертификатов.
  412. Цепочка сертификатов -- это коллекция, в которой каждый следующий сертификат
  413. выпущен владельцем предыдущего.
  414. *******************************************************************************
  415. */
  416. /*! \brief Создание коллекции сертификатов
  417. По строке descr, в которой через пробел перечисляются имена файлов
  418. сертификатов, создается коллекция [?cert_len]certs.
  419. \return ERR_OK, если коллекция создана, и код ошибки в противном случае.
  420. */
  421. err_t cmdCVCsCreate(
  422. octet* certs, /*!< [out] коллекция сертификатов */
  423. size_t* count, /*!< [out] длина коллекции (в октетах) */
  424. const char* descr /*!< [in] описание коллекции */
  425. );
  426. /*! \brief Число сертификатов в коллекции
  427. Определяется число count сертификатов в коллекции [certs_len]certs.
  428. \return ERR_OK, если число сертификатов определено, и код ошибки
  429. в противном случае.
  430. */
  431. err_t cmdCVCsCount(
  432. size_t* count, /*!< [out] число сертификатов */
  433. const octet* certs, /*!< [in] коллекция сертификатов */
  434. size_t certs_len /*!< [in] длина коллекции */
  435. );
  436. /*! \brief Получение сертификата коллекции
  437. В коллекции [certs_len]certs определяется сертификат с номером num.
  438. Его смещение в коллекции возвращается по адресу offset, а длина --
  439. по адресу cert_len.
  440. \return ERR_OK, если сертификат получен, и код ошибки в противном случае.
  441. \remark Любой из адресов offset, cert_len может быть нулевым, и тогда
  442. данные по этому адресу не возвращаются.
  443. */
  444. err_t cmdCVCsGet(
  445. size_t* offset, /*!< [out] смещение сертификата */
  446. size_t* cert_len, /*!< [out] длина сертификата */
  447. const octet* certs, /*!< [in] коллекция сертификатов */
  448. size_t certs_len, /*!< [in] длина коллекции */
  449. size_t num /*!< [in] номер сертификата */
  450. );
  451. /*! \brief Получение последнего сертификата коллекции
  452. В коллекции [certs_len]certs определяется последний сертификат.
  453. Его смещение в коллекции возвращается по адресу offset, а длина --
  454. по адресу cert_len.
  455. \return ERR_OK, если сертификат получен, и код ошибки в противном случае.
  456. \remark Любой из адресов offset, cert_len может быть нулевым, и тогда
  457. данные по этому адресу не возвращаются.
  458. */
  459. err_t cmdCVCsGetLast(
  460. size_t* offset, /*!< [out] смещение сертификата */
  461. size_t* cert_len, /*!< [out] длина сертификата */
  462. const octet* certs, /*!< [in] коллекция сертификатов */
  463. size_t certs_len /*!< [in] длина коллекции */
  464. );
  465. /*! \brief Поиск сертификата в коллекции
  466. В коллекции [certs_len]certs ведется поиск сертификата [cert_len]cert.
  467. Его смещение в коллекции возвращается по адресу offset.
  468. \return ERR_OK, если сертификат найден, и код ошибки в противном случае.
  469. \remark Адрес offset может быть нулевым, и тогда данные по этому адресу
  470. не возвращаются.
  471. */
  472. err_t cmdCVCsFind(
  473. size_t* offset, /*!< [out] смещение сертификата */
  474. const octet* certs, /*!< [in] коллекция сертификатов */
  475. size_t certs_len, /*!< [in] длина коллекции */
  476. const octet* cert, /*!< [in] cертификат */
  477. size_t cert_len /*!< [in] длина сертификата */
  478. );
  479. /*! \brief Проверка коллекции сертификатов
  480. Проверяется корректность сертификатов коллекции [certs_len]certs.
  481. \return ERR_OK, если проверка прошла успешно, и код ошибки
  482. в противном случае.
  483. */
  484. err_t cmdCVCsCheck(
  485. const octet* certs, /*!< [in] коллекция сертификатов */
  486. size_t certs_len /*!< [in] длина коллекции */
  487. );
  488. /*! \brief Проверка цепочки сертификатов
  489. Проверяется корректность цепочки сертификатов [certs_len]certs
  490. на дату date.
  491. \return ERR_OK, если проверка прошла успешно, и код ошибки
  492. в противном случае.
  493. \remakr Дата date должна попадать в срок действия последнего сертификата
  494. цепочки.
  495. \remark Указатель date может быть нулевым или массив date может быть
  496. заполнен нулями, и тогда дата игнорируется.
  497. */
  498. err_t cmdCVCsVal(
  499. const octet* certs, /*!< [in] цепочка сертификатов */
  500. size_t certs_len, /*!< [in] длина цепочки (в октетах) */
  501. const octet date[6] /*!< [in] дата проверки */
  502. );
  503. /*! \brief Печать коллекции сертификатов
  504. Печатается коллекция сертификатов [certs_len]certs.
  505. \return ERR_OK, если печать успешно выполнена, и код ошибки
  506. в противном случае.
  507. */
  508. err_t cmdCVCsPrint(
  509. const octet* certs, /*!< [in] коллекция сертификатов */
  510. size_t certs_len /*!< [in] длина коллекции */
  511. );
  512. /*
  513. *******************************************************************************
  514. ЭЦП
  515. ЭЦП может сопровождаться (обратной) цепочкой CV-сертификатов. Первым в цепочке
  516. идет сертификат подписанта. Каждый следующий сертификат -- это сертификат
  517. удостоверяющего центра, выпустившего предыдущий сертификат.
  518. ЭЦП может сопровождаться датой выработки подписи. Дата задается 6 октетами
  519. по схеме YYMMDD, которая используется в CV-сертификатах (см. btok.h).
  520. Если все октеты нулевые, то значит дата не указана.
  521. Цепочка сертификатов и дата подписываются вместе с содержимым целевого файла.
  522. При этом смена сертификата подписанта в цепочке сделает подпись
  523. недействительной, даже если открытый ключ будет повторен в двух сертификатах
  524. (см. RFC5035: описание угроз, описание атрибута SigningCertificateV2).
  525. Формат ЭЦП:
  526. \code
  527. Signature ::= SEQUENCE
  528. {
  529. certs SEQUENCE OF CVCertificate,
  530. sig OCTET STRING(SIZE(48|72|96)),
  531. date CVDate OPTIONAL
  532. }
  533. CVDate ::= OCTET STRING(SIZE(6))
  534. \endcode
  535. Для управления форматом предусмотрена структура cmd_sig_t. В поле certs этой
  536. структуры cmd_sig_t размещается цепочка сертификатов. Сертификаты цепочки
  537. записываются последовательно друг за другом без разделителей. Сертификаты
  538. закодированы по правилам АСН.1, их длины однозначно определяются в ходе
  539. декодирования. Дата (date) и подпись (sig) также кодируются по правилам
  540. АСН.1.
  541. DER-код структуры Signature (строка октетов) переворачивается. За счет
  542. переворота DER-код однозначно декодируется даже будучи записанным в конец
  543. файла произвольного размера. В частности, подпись может быть присоединена
  544. к подписывемому файлу. В этом случае при проверке подписи она исключается
  545. из контролируемого содержимого файла.
  546. *******************************************************************************
  547. */
  548. /*! \brief Подпись и сопровождающие сертификаты */
  549. typedef struct {
  550. octet sig[96]; /*!< подпись */
  551. size_t sig_len; /*!< длина подписи в октетах */
  552. octet certs[1460]; /*!< цепочка сертификатов */
  553. size_t certs_len; /*!< cуммарная длина сертификатов */
  554. octet date[6]; /*!< дата выработки подписи */
  555. } cmd_sig_t;
  556. /*! \brief Подпись файла
  557. Содержимое файла file подписывается на личном ключе [privkey_len]privkey
  558. с указанием date в качестве даты подписания. При передаче нулевого буфера
  559. date дата подписания не указывается.Подпись сохраняется в файле sig_file
  560. вместе с сертификатами цепочки certs. Цепочка certs может быть пустой.
  561. В качестве файла подписи можно указать подписываемый файл, и тогда подпись
  562. записывается в его конец.
  563. \expect{ERR_BAD_KEYPAIR} Если цепочка certs непуста, то ее первый
  564. сертификат соответствует privkey.
  565. \expect{ERR_BAD_CERT} Если цепочка certs непуста, то каждый ее сертификат,
  566. начиная со второго, -- это сертификат удостоверяющего центра, выпустившего
  567. предыдущий сертификат.
  568. \expect{ERR_BAD_DATE} Если дата подписания date указана, то она корректна.
  569. \expect{ERR_OUTOFRANGE} Если дата подписания date указана, то все
  570. сертификаты цепочки certs действительны на эту дату.
  571. \return ERR_OK, если файл успешно подписан, и код ошибки в противном
  572. случае.
  573. \remark В списке certs указываются имена файлов сертификатов. Имена
  574. разделяются пробелами. Имена могут окаймляться кавычками.
  575. \remark Файлы file и sig_file могут совпадать, и тогда подпись
  576. присоединяется к подписываемому файлу.
  577. */
  578. err_t cmdSigSign(
  579. const char* sig_file, /*!< [in] файл подписи */
  580. const char* file, /*!< [in] подписываемый файл */
  581. const char* certs, /*!< [in] цепочка сертификатов */
  582. const octet date[6], /*!< [in] дата подписания */
  583. const octet privkey[], /*!< [in] личный ключ */
  584. size_t privkey_len /*!< [in] длина личного ключа */
  585. );
  586. /*! \brief Чтение подписи
  587. Из файла sig_file прочитывается подпись sig. При ненулевом sig_len по этому
  588. адресу возвращается длина DER-кода подписи.
  589. \return ERR_OK, если подпись успешно прочитана, и код ошибки в противном
  590. случае.
  591. */
  592. err_t cmdSigRead(
  593. cmd_sig_t* sig, /*!< [out] подпись */
  594. size_t* sig_len, /*!< [out] длина DER-кода подписи */
  595. const char* sig_file /*!< [in] файл с подписью */
  596. );
  597. /*! \brief Проверка подписи файла на открытом ключе
  598. Подпись содержимого файла file, размещенная в sig_file, проверяется
  599. на открытом ключе [pubkey_len]pubkey. В качестве файла подписи может
  600. указывать подписываемый файл, и тогда подпись прочитывается из его конца
  601. и исключается из содержимого файла при проверке.
  602. \expect{ERR_BAD_KEYPAIR} Если подпись сопровождается цепочкой сертификатов,
  603. то ее первый сертификат соответствует pubkey.
  604. \expect{ERR_BAD_CERT} Если подпись сопровождается цепочкой сертификатов,
  605. то каждый ее сертификат, начиная со второго, -- это сертификат
  606. удостоверяющего центра, выпустившего предыдущий сертификат.
  607. \expect{ERR_BAD_DATE} Если подпись сопровождается датой подписания,
  608. то эта дата корректна.
  609. \expect{ERR_OUTOFRANGE} Если подпись сопровождается датой подписания, то все
  610. сертификаты вложеннной цепочки действительны на эту дату.
  611. \expect{ERR_BAD_FORMAT} Если подпись размещается в отдельном файле, то этот
  612. файл содержит исключительно подпись.
  613. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  614. */
  615. err_t cmdSigVerify(
  616. const char* file, /*!< [in] подписанный файл */
  617. const char* sig_file, /*!< [in] файл подписи */
  618. const octet pubkey[], /*!< [in] открытый ключ */
  619. size_t pubkey_len /*!< [in] длина открытого ключа */
  620. );
  621. /*! \brief Проверка подписи файла на доверенном сертификате
  622. Подпись содержимого файла file, размещенная в sig_file, проверяется
  623. на доверенном сертификате [anchor_len]anchor. Проверка будет завершена
  624. успешно, если подпись сопровождается цепочкой сертификатов и признается
  625. корректной на первом сертификате цепочки. В качестве файла подписи может
  626. указывать подписываемый файл, и тогда подпись прочитывается из его конца
  627. и исключается из содержимого файла при проверке.
  628. \expect{ERR_NO_TRUST} Один из сертификатов цепочки совпадает с anchor.
  629. \expect{ERR_BAD_CERT} Каждый сертификат цепочки, начиная со второго, --
  630. это сертификат удостоверяющего центра, выпустившего предыдущий сертификат.
  631. \expect{ERR_BAD_DATE} Если подпись сопровождается датой подписания,
  632. то эта дата корректна.
  633. \expect{ERR_OUTOFRANGE} Если подпись сопровождается датой подписания, то все
  634. сертификаты вложеннной цепочки действительны на эту дату.
  635. \expect{ERR_BAD_FORMAT} Если подпись размещается в отдельном файле, то этот
  636. файл содержит исключительно подпись.
  637. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  638. */
  639. err_t cmdSigVerify2(
  640. const char* file, /*!< [in] подписанный файл */
  641. const char* sig_file, /*!< [in] файл подписи */
  642. const octet anchor[], /*!< [in] доверенный сертификат */
  643. size_t anchor_len /*!< [in] длина anchor */
  644. );
  645. /*! \brief Самопроверка подписи на открытом ключе
  646. Подпись исполнимого файла, в котором вызывается данная функция,
  647. прочитывается из конца этого же файла и проверяется на открытом ключе
  648. [pubkey_len]pubkey через обращение к cmdSigVerify(pubkey, pubkey_len).
  649. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  650. */
  651. err_t cmdSigSelfVerify(
  652. const octet pubkey[], /*!< [in] открытый ключ */
  653. size_t pubkey_len /*!< [in] длина открытого ключа */
  654. );
  655. /*! \brief Самопроверка подписи на доверенном сертификате
  656. Подпись исполнимого файла, в котором вызывается данная функция,
  657. прочитывается из конца этого же файла и проверяется на доверенном
  658. сертификате [anchor_len]anchor через обращение к
  659. cmdSigVerify2(anchor, anchor_len).
  660. \return ERR_OK, если подпись корректна, и код ошибки в противном случае.
  661. */
  662. err_t cmdSigSelfVerify2(
  663. const octet anchor[], /*!< [in] доверенный сертификат */
  664. size_t anchor_len /*!< [in] длина anchor */
  665. );
  666. /*! \brief Извлечение объекта из подписи
  667. Из подписи, размещенной в файле sig_file, извлекается и сохраняется в файле
  668. file объект, описанный строкой scope:
  669. - n-й сертификат, если scope == "cert<n>" (нумерация от нуля, сертификат
  670. подписанта идет последним);
  671. - подписанное содержимое, если scope == "body";
  672. - собственно подпись, если scope == "sig".
  673. \return ERR_OK, если объект успешно извлечен, и код ошибки в противном
  674. случае.
  675. */
  676. err_t cmdSigExtr(
  677. const char* obj_file, /*!< [in] файл c объектом */
  678. const char* sig_file, /*!< [in] файл подписи */
  679. const char* scope /*!< [in] область */
  680. );
  681. /*! \brief Печать подписи
  682. Печатается область подписи, размещенной в конце файла sig_file. Область
  683. задается строкой scope:
  684. - если scope != 0, то печатается поле с именем scope ("certnum", "date");
  685. - если scope == 0, то печатается вся подпись.
  686. \return ERR_OK, если печать успешно выполнена, и код ошибки
  687. в противном случае.
  688. */
  689. err_t cmdSigPrint(
  690. const char* sig_file, /*!< [in] файл подписи */
  691. const char* scope /*!< [in] область печати */
  692. );
  693. #ifdef __cplusplus
  694. } /* extern "C" */
  695. #endif
  696. #endif /* __BEE2_CMD_H */