OTPChecker.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /**
  2. * @file OTPChecker.c
  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. #include <security/OTPChecker.h>
  23. static void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t);
  24. static void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp);
  25. static void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv);
  26. static int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp);
  27. void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t)
  28. {
  29. for (int i = 0; i < mc->num_entries; i++) {
  30. oc_table_entries_at(&mc->tables_params.tables_params, t, i)->avail = -1;
  31. }
  32. }
  33. void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp)
  34. {
  35. // calculate starting index
  36. int start_index = otp % mc->num_entries;
  37. // try indexes starting with the base position
  38. for (int i = 0; i < mc->num_entries; i++) {
  39. int index = BMODADD(start_index, i, mc->num_entries);
  40. struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
  41. // if we find a free index, use it
  42. if (entry->avail < 0) {
  43. entry->otp = otp;
  44. entry->avail = 1;
  45. return;
  46. }
  47. // if we find a used index with the same mac,
  48. // use it by incrementing its count
  49. if (entry->otp == otp) {
  50. entry->avail++;
  51. return;
  52. }
  53. }
  54. // will never add more macs than we can hold
  55. ASSERT(0)
  56. }
  57. void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv)
  58. {
  59. // calculate values
  60. otp_t *otps = OTPCalculator_Generate(calc, key, iv, 0);
  61. // empty table
  62. OTPChecker_Table_Empty(mc ,t);
  63. // add calculated values to table
  64. for (int i = 0; i < mc->num_otps; i++) {
  65. OTPChecker_Table_AddOTP(mc, t, otps[i]);
  66. }
  67. }
  68. int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp)
  69. {
  70. // calculate starting index
  71. int start_index = otp % mc->num_entries;
  72. // try indexes starting with the base position
  73. for (int i = 0; i < mc->num_entries; i++) {
  74. int index = BMODADD(start_index, i, mc->num_entries);
  75. struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
  76. // if we find an empty entry, there is no such mac
  77. if (entry->avail < 0) {
  78. return 0;
  79. }
  80. // if we find a matching entry, check its count
  81. if (entry->otp == otp) {
  82. if (entry->avail > 0) {
  83. entry->avail--;
  84. return 1;
  85. }
  86. return 0;
  87. }
  88. }
  89. // there are always empty slots
  90. ASSERT(0)
  91. return 0;
  92. }
  93. int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables)
  94. {
  95. ASSERT(num_otps > 0)
  96. ASSERT(BEncryption_cipher_valid(cipher))
  97. ASSERT(num_tables > 0)
  98. // init arguments
  99. mc->num_otps = num_otps;
  100. mc->num_tables = num_tables;
  101. // set number of entries
  102. mc->num_entries = 2 * mc->num_otps;
  103. // set no tables used
  104. mc->tables_used = 0;
  105. mc->next_table = 0;
  106. // initialize calculator
  107. if (!OTPCalculator_Init(&mc->calc, mc->num_otps, cipher)) {
  108. goto fail0;
  109. }
  110. // allocate tables
  111. oc_tablesParams_Init(&mc->tables_params, mc->num_tables, mc->num_entries);
  112. if (!(mc->tables = malloc(mc->tables_params.len))) {
  113. goto fail1;
  114. }
  115. // initialize tables
  116. for (int i = 0; i < mc->num_tables; i++) {
  117. OTPChecker_Table_Empty(mc, oc_tables_tables_at(&mc->tables_params, mc->tables, i));
  118. }
  119. // init debug object
  120. DebugObject_Init(&mc->d_obj);
  121. return 1;
  122. fail1:
  123. OTPCalculator_Free(&mc->calc);
  124. fail0:
  125. return 0;
  126. }
  127. void OTPChecker_Free (OTPChecker *mc)
  128. {
  129. // free debug object
  130. DebugObject_Free(&mc->d_obj);
  131. // free tables
  132. free(mc->tables);
  133. // free calculator
  134. OTPCalculator_Free(&mc->calc);
  135. }
  136. void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv)
  137. {
  138. ASSERT(mc->next_table >= 0)
  139. ASSERT(mc->next_table < mc->num_tables)
  140. // initialize next table
  141. oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, mc->next_table);
  142. *oc_table_id(&mc->tables_params.tables_params, table) = seed_id;
  143. OTPChecker_Table_Generate(mc, table, &mc->calc, key, iv);
  144. // update next table number
  145. mc->next_table = BMODADD(mc->next_table, 1, mc->num_tables);
  146. // update number of used tables if not all are used yet
  147. if (mc->tables_used < mc->num_tables) {
  148. mc->tables_used++;
  149. }
  150. }
  151. void OTPChecker_RemoveSeeds (OTPChecker *mc)
  152. {
  153. mc->tables_used = 0;
  154. mc->next_table = 0;
  155. }
  156. int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp)
  157. {
  158. // try tables in reverse order
  159. for (int i = 1; i <= mc->tables_used; i++) {
  160. int table_index = BMODADD(mc->next_table, mc->num_tables - i, mc->num_tables);
  161. oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, table_index);
  162. if (*oc_table_id(&mc->tables_params.tables_params, table) == seed_id) {
  163. return OTPChecker_Table_CheckOTP(mc, table, otp);
  164. }
  165. }
  166. return 0;
  167. }