es.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. *******************************************************************************
  3. \file es.c
  4. \brief Dealing with entropy sources
  5. \project bee2/cmd
  6. \created 2021.04.20
  7. \version 2023.12.16
  8. \copyright The Bee2 authors
  9. \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
  10. *******************************************************************************
  11. */
  12. #include "../cmd.h"
  13. #include <bee2/core/err.h>
  14. #include <bee2/core/dec.h>
  15. #include <bee2/core/mem.h>
  16. #include <bee2/core/rng.h>
  17. #include <bee2/core/str.h>
  18. #include <bee2/core/mt.h>
  19. #include <bee2/core/tm.h>
  20. #include <bee2/core/util.h>
  21. #include <bee2/core/word.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. /*
  25. *******************************************************************************
  26. Утилита es
  27. Функционал:
  28. - перечень доступных источников энтропии;
  29. - проверка работоспосбности источников энтропии;
  30. - выгрузка данных от стандартных источников энтропии;
  31. - эксперименты с источником timer.
  32. Пример:
  33. bee2cmd es print
  34. bee2cmd es read trng2 128 file
  35. *******************************************************************************
  36. */
  37. static const char _name[] = "es";
  38. static const char _descr[] = "dealing with entropy sources";
  39. static int esUsage()
  40. {
  41. printf(
  42. "bee2cmd/%s: %s\n"
  43. "Usage:\n"
  44. " es print\n"
  45. " list available entropy sources and determine their health\n"
  46. " es read <source> <count> <file>\n"
  47. " read <count> Kbytes from <source> and store them in <file>\n"
  48. " <source> in {trng, trng2, sys, sys2, timer, timerNN}\n"
  49. " timerNNN -- use NNN sleep delays to produce one output bit\n"
  50. ,
  51. _name, _descr
  52. );
  53. return -1;
  54. }
  55. /*
  56. *******************************************************************************
  57. Информация об источниках энтропии
  58. print
  59. *******************************************************************************
  60. */
  61. static err_t esPrint(int argc, char* argv[])
  62. {
  63. const char* sources[] = { "trng", "trng2", "sys", "sys2", "timer" };
  64. size_t pos;
  65. size_t count;
  66. size_t read;
  67. // проверить параметры
  68. if (argc != 0)
  69. return ERR_CMD_PARAMS;
  70. // опрос источников
  71. printf("Sources:");
  72. for (pos = count = 0; pos < COUNT_OF(sources); ++pos)
  73. if (rngESRead(&read, 0, 0, sources[pos]) == ERR_OK)
  74. {
  75. printf(" %s%c", sources[pos],
  76. rngESTest(sources[pos]) == ERR_OK ? '+' : '-');
  77. ++count;
  78. }
  79. printf(count ? "\n" : " none\n");
  80. // общая работоспособность
  81. printf("Health (at least two healthy sources): %c\n",
  82. rngESHealth() == ERR_OK ? '+' : '-');
  83. printf("Health2 (there is a healthy physical source): %c\n",
  84. rngESHealth2() == ERR_OK ? '+' : '-');
  85. printf("\\warning health is volatile\n");
  86. return ERR_OK;
  87. }
  88. /*
  89. *******************************************************************************
  90. Чтение данных
  91. es read <source> <count> <file>
  92. *******************************************************************************
  93. */
  94. static err_t rngReadSourceEx(size_t* read, void* buf, size_t count,
  95. const char* source_name, size_t par)
  96. {
  97. if (strEq(source_name, "trng") || strEq(source_name, "trng2") ||
  98. strEq(source_name, "sys") ||
  99. strEq(source_name, "timer") && par == 0)
  100. return rngESRead(read, buf, count, source_name);
  101. // эксперименты с источником timer
  102. {
  103. register tm_ticks_t ticks;
  104. register tm_ticks_t t;
  105. register word w;
  106. size_t i, j, reps;
  107. // pre
  108. ASSERT(memIsValid(read, sizeof(size_t)));
  109. ASSERT(memIsValid(buf, count));
  110. // генерация
  111. for (i = 0; i < count; ++i)
  112. {
  113. ((octet*)buf)[i] = 0;
  114. ticks = tmTicks();
  115. for (j = 0; j < 8; ++j)
  116. {
  117. w = 0;
  118. for (reps = 0; reps < par; ++reps)
  119. {
  120. mtSleep(0);
  121. t = tmTicks();
  122. w ^= (word)(t - ticks);
  123. ticks = t;
  124. }
  125. ((octet*)buf)[i] ^= wordParity(w) << j;
  126. }
  127. }
  128. ticks = t = 0, w = 0;
  129. *read = count;
  130. return ERR_OK;
  131. }
  132. return ERR_OK;
  133. }
  134. static err_t esRead(int argc, char *argv[])
  135. {
  136. err_t code;
  137. char source[6];
  138. size_t par = 0;
  139. size_t count;
  140. FILE* fp;
  141. octet buf[2048];
  142. // разбор командной строки: число параметров
  143. if (argc != 3)
  144. return ERR_CMD_PARAMS;
  145. // разбор командной строки: источник энтропии
  146. if (strEq(argv[0], "trng"))
  147. strCopy(source, "trng");
  148. else if (strEq(argv[0], "trng2"))
  149. strCopy(source, "trng2");
  150. else if (strEq(argv[0], "sys"))
  151. strCopy(source, "sys");
  152. else if (strEq(argv[0], "timer"))
  153. strCopy(source, "timer");
  154. else if (strStartsWith(argv[0], "timer"))
  155. {
  156. strCopy(source, "timer");
  157. argv[0] += strLen("timer");
  158. if (!decIsValid(argv[0]) || !strLen(argv[0]) ||
  159. strLen(argv[0]) > 3 || decCLZ(argv[0]))
  160. return ERR_CMD_PARAMS;
  161. par = (size_t)decToU32(argv[0]);
  162. }
  163. else
  164. return ERR_CMD_PARAMS;
  165. // разбор командной строки: число Кбайтов
  166. if (!decIsValid(argv[1]) || !strLen(argv[1]) ||
  167. strLen(argv[1]) > 4 || decCLZ(argv[1]))
  168. return ERR_CMD_PARAMS;
  169. count = (size_t)decToU32(argv[1]);
  170. if (((count << 10) >> 10) != count)
  171. return ERR_OUTOFRANGE;
  172. count <<= 10;
  173. // разбор командной строки: имя выходного файла
  174. code = cmdFileValNotExist(1, argv + 2);
  175. ERR_CALL_CHECK(code);
  176. fp = fopen(argv[2], "wb");
  177. if (!fp)
  178. return ERR_FILE_OPEN;
  179. // выгрузка данных
  180. while (count)
  181. {
  182. size_t read;
  183. // читать
  184. code = rngReadSourceEx(&read, buf,
  185. MIN2(sizeof(buf), count), source, par);
  186. ERR_CALL_HANDLE(code, fclose(fp));
  187. code = read == MIN2(sizeof(buf), count) ? ERR_OK : ERR_FILE_READ;
  188. ERR_CALL_HANDLE(code, fclose(fp));
  189. // писать
  190. code = fwrite(buf, 1, read, fp) == read ? ERR_OK : ERR_FILE_WRITE;
  191. ERR_CALL_HANDLE(code, fclose(fp));
  192. count -= read;
  193. }
  194. // завершение
  195. fclose(fp);
  196. return ERR_OK;
  197. }
  198. /*
  199. *******************************************************************************
  200. Главная функция
  201. *******************************************************************************
  202. */
  203. int esMain(int argc, char* argv[])
  204. {
  205. err_t code;
  206. // справка
  207. if (argc < 2)
  208. return esUsage();
  209. // разбор команды
  210. ++argv, --argc;
  211. if (strEq(argv[0], "print"))
  212. code = esPrint(argc - 1, argv + 1);
  213. else if (strEq(argv[0], "read"))
  214. code = esRead(argc - 1, argv + 1);
  215. else
  216. code = ERR_CMD_NOT_FOUND;
  217. // завершить
  218. if (code != ERR_OK)
  219. printf("bee2cmd/%s: %s\n", _name, errMsg(code));
  220. return (int)code;
  221. }
  222. /*
  223. *******************************************************************************
  224. Инициализация
  225. *******************************************************************************
  226. */
  227. err_t esInit()
  228. {
  229. return cmdReg(_name, _descr, esMain);
  230. }