OTPChecker.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /**
  2. * @file OTPChecker.h
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. * @section DESCRIPTION
  23. *
  24. * Object that checks OTPs agains known seeds.
  25. */
  26. #ifndef BADVPN_SECURITY_OTPCHECKER_H
  27. #define BADVPN_SECURITY_OTPCHECKER_H
  28. #include <stdint.h>
  29. #include <misc/balign.h>
  30. #include <misc/debug.h>
  31. #include <misc/modadd.h>
  32. #include <security/OTPCalculator.h>
  33. #include <system/DebugObject.h>
  34. struct OTPChecker_entry {
  35. otp_t otp;
  36. int avail;
  37. };
  38. #include <generated/bstruct_OTPChecker.h>
  39. /**
  40. * Object that checks OTPs agains known seeds.
  41. */
  42. typedef struct {
  43. DebugObject d_obj;
  44. int num_otps;
  45. int num_entries;
  46. int num_tables;
  47. int tables_used;
  48. int next_table;
  49. OTPCalculator calc;
  50. oc_tablesParams tables_params;
  51. oc_tables *tables;
  52. } OTPChecker;
  53. /**
  54. * Initializes the checker.
  55. *
  56. * @param mc the object
  57. * @param num_otps number of OTPs to generate from a seed. Must be >0.
  58. * @param cipher encryption cipher for calculating the OTPs. Must be valid
  59. * according to {@link BEncryption_cipher_valid}.
  60. * @param num_tables number of tables to keep, each for one seed. Must be >0.
  61. * @return 1 on success, 0 on failure
  62. */
  63. static int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables) WARN_UNUSED;
  64. /**
  65. * Frees the checker.
  66. *
  67. * @param mc the object
  68. */
  69. static void OTPChecker_Free (OTPChecker *mc);
  70. /**
  71. * Adds a seed whose OTPs should be recognized.
  72. *
  73. * @param mc the object
  74. * @param seed_id seed identifier
  75. * @param key encryption key
  76. * @param iv initialization vector
  77. */
  78. static void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv);
  79. /**
  80. * Removes all active seeds.
  81. *
  82. * @param mc the object
  83. */
  84. static void OTPChecker_RemoveSeeds (OTPChecker *mc);
  85. /**
  86. * Checks an OTP.
  87. *
  88. * @param mc the object
  89. * @param seed_id identifer of seed whom the OTP is claimed to belong to
  90. * @param otp OTP to check
  91. * @return 1 if the OTP is valid, 0 if not
  92. */
  93. static int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp);
  94. static void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t);
  95. static void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp);
  96. static void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv);
  97. static int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp);
  98. void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t)
  99. {
  100. for (int i = 0; i < mc->num_entries; i++) {
  101. oc_table_entries_at(&mc->tables_params.tables_params, t, i)->avail = -1;
  102. }
  103. }
  104. void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp)
  105. {
  106. // calculate starting index
  107. int start_index = otp % mc->num_entries;
  108. // try indexes starting with the base position
  109. for (int i = 0; i < mc->num_entries; i++) {
  110. int index = BMODADD(start_index, i, mc->num_entries);
  111. struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
  112. // if we find a free index, use it
  113. if (entry->avail < 0) {
  114. entry->otp = otp;
  115. entry->avail = 1;
  116. return;
  117. }
  118. // if we find a used index with the same mac,
  119. // use it by incrementing its count
  120. if (entry->otp == otp) {
  121. entry->avail++;
  122. return;
  123. }
  124. }
  125. // will never add more macs than we can hold
  126. ASSERT(0)
  127. }
  128. void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv)
  129. {
  130. // calculate values
  131. otp_t *otps = OTPCalculator_Generate(calc, key, iv, 0);
  132. // empty table
  133. OTPChecker_Table_Empty(mc ,t);
  134. // add calculated values to table
  135. for (int i = 0; i < mc->num_otps; i++) {
  136. OTPChecker_Table_AddOTP(mc, t, otps[i]);
  137. }
  138. }
  139. int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp)
  140. {
  141. // calculate starting index
  142. int start_index = otp % mc->num_entries;
  143. // try indexes starting with the base position
  144. for (int i = 0; i < mc->num_entries; i++) {
  145. int index = BMODADD(start_index, i, mc->num_entries);
  146. struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
  147. // if we find an empty entry, there is no such mac
  148. if (entry->avail < 0) {
  149. return 0;
  150. }
  151. // if we find a matching entry, check its count
  152. if (entry->otp == otp) {
  153. if (entry->avail > 0) {
  154. entry->avail--;
  155. return 1;
  156. }
  157. return 0;
  158. }
  159. }
  160. // there are always empty slots
  161. ASSERT(0)
  162. return 0;
  163. }
  164. int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables)
  165. {
  166. ASSERT(num_otps > 0)
  167. ASSERT(BEncryption_cipher_valid(cipher))
  168. ASSERT(num_tables > 0)
  169. // init arguments
  170. mc->num_otps = num_otps;
  171. mc->num_tables = num_tables;
  172. // set number of entries
  173. mc->num_entries = 2 * mc->num_otps;
  174. // set no tables used
  175. mc->tables_used = 0;
  176. mc->next_table = 0;
  177. // initialize calculator
  178. if (!OTPCalculator_Init(&mc->calc, mc->num_otps, cipher)) {
  179. goto fail0;
  180. }
  181. // allocate tables
  182. oc_tablesParams_Init(&mc->tables_params, mc->num_tables, mc->num_entries);
  183. if (!(mc->tables = malloc(mc->tables_params.len))) {
  184. goto fail1;
  185. }
  186. // initialize tables
  187. for (int i = 0; i < mc->num_tables; i++) {
  188. OTPChecker_Table_Empty(mc, oc_tables_tables_at(&mc->tables_params, mc->tables, i));
  189. }
  190. // init debug object
  191. DebugObject_Init(&mc->d_obj);
  192. return 1;
  193. fail1:
  194. OTPCalculator_Free(&mc->calc);
  195. fail0:
  196. return 0;
  197. }
  198. void OTPChecker_Free (OTPChecker *mc)
  199. {
  200. // free debug object
  201. DebugObject_Free(&mc->d_obj);
  202. // free tables
  203. free(mc->tables);
  204. // free calculator
  205. OTPCalculator_Free(&mc->calc);
  206. }
  207. void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv)
  208. {
  209. ASSERT(mc->next_table >= 0)
  210. ASSERT(mc->next_table < mc->num_tables)
  211. // initialize next table
  212. oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, mc->next_table);
  213. *oc_table_id(&mc->tables_params.tables_params, table) = seed_id;
  214. OTPChecker_Table_Generate(mc, table, &mc->calc, key, iv);
  215. // update next table number
  216. mc->next_table = BMODADD(mc->next_table, 1, mc->num_tables);
  217. // update number of used tables if not all are used yet
  218. if (mc->tables_used < mc->num_tables) {
  219. mc->tables_used++;
  220. }
  221. }
  222. void OTPChecker_RemoveSeeds (OTPChecker *mc)
  223. {
  224. mc->tables_used = 0;
  225. mc->next_table = 0;
  226. }
  227. int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp)
  228. {
  229. // try tables in reverse order
  230. for (int i = 1; i <= mc->tables_used; i++) {
  231. int table_index = BMODADD(mc->next_table, mc->num_tables - i, mc->num_tables);
  232. oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, table_index);
  233. if (*oc_table_id(&mc->tables_params.tables_params, table) == seed_id) {
  234. return OTPChecker_Table_CheckOTP(mc, table, otp);
  235. }
  236. }
  237. return 0;
  238. }
  239. #endif