slip39.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /**
  2. * This file is part of the TREZOR project, https://trezor.io/
  3. *
  4. * Copyright (c) SatoshiLabs
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the "Software"),
  8. * to deal in the Software without restriction, including without limitation
  9. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the
  11. * Software is furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included
  14. * in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
  20. * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22. * OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. #include "slip39.h"
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "slip39_wordlist.h"
  28. /**
  29. * Returns word at position `index`.
  30. */
  31. const char* get_word(uint16_t index) {
  32. if(index >= WORDS_COUNT) {
  33. return NULL;
  34. }
  35. return slip39_wordlist[index];
  36. }
  37. /**
  38. * Finds the index of a given word.
  39. * Returns true on success and stores result in `index`.
  40. */
  41. bool word_index(uint16_t* index, const char* word, uint8_t word_length) {
  42. uint16_t lo = 0;
  43. uint16_t hi = WORDS_COUNT;
  44. uint16_t mid = 0;
  45. while((hi - lo) > 1) {
  46. mid = (hi + lo) / 2;
  47. if(strncmp(slip39_wordlist[mid], word, word_length) > 0) {
  48. hi = mid;
  49. } else {
  50. lo = mid;
  51. }
  52. }
  53. if(strncmp(slip39_wordlist[lo], word, word_length) != 0) {
  54. return false;
  55. }
  56. *index = lo;
  57. return true;
  58. }
  59. /**
  60. * Returns the index of the first sequence in words_button_seq[] which is not
  61. * less than the given sequence. Returns WORDS_COUNT if there is no such
  62. * sequence.
  63. */
  64. static uint16_t find_sequence(uint16_t sequence) {
  65. if(sequence <= words_button_seq[0].sequence) {
  66. return 0;
  67. }
  68. uint16_t lo = 0;
  69. uint16_t hi = WORDS_COUNT;
  70. while(hi - lo > 1) {
  71. uint16_t mid = (hi + lo) / 2;
  72. if(words_button_seq[mid].sequence >= sequence) {
  73. hi = mid;
  74. } else {
  75. lo = mid;
  76. }
  77. }
  78. return hi;
  79. }
  80. /**
  81. * Returns a word matching the button sequence prefix or NULL if no match is
  82. * found.
  83. */
  84. const char* button_sequence_to_word(uint16_t sequence) {
  85. if(sequence == 0) {
  86. return slip39_wordlist[words_button_seq[0].index];
  87. }
  88. uint16_t multiplier = 1;
  89. while(sequence < 1000) {
  90. sequence *= 10;
  91. multiplier *= 10;
  92. }
  93. uint16_t i = find_sequence(sequence);
  94. if(i >= WORDS_COUNT || words_button_seq[i].sequence - sequence >= multiplier) {
  95. return NULL;
  96. }
  97. return slip39_wordlist[words_button_seq[i].index];
  98. }
  99. /**
  100. * Calculates which buttons on the T9 keyboard can still be pressed after the
  101. * prefix was entered. Returns a 9-bit bitmask, where each bit specifies which
  102. * buttons can be pressed (there are still words in this combination). The least
  103. * significant bit corresponds to the first button.
  104. *
  105. * Example: 110000110 - second, third, eighth and ninth button still can be
  106. * pressed.
  107. */
  108. uint16_t slip39_word_completion_mask(uint16_t prefix) {
  109. if(prefix >= 1000) {
  110. // Four char prefix -> the mask is zero.
  111. return 0;
  112. }
  113. // Determine the range of sequences [min, max), which have the given prefix.
  114. uint16_t min = prefix;
  115. uint16_t max = prefix + 1;
  116. uint16_t divider = 1;
  117. while(max <= 1000) {
  118. min *= 10;
  119. max *= 10;
  120. divider *= 10;
  121. }
  122. divider /= 10;
  123. // Determine the range we will be searching in words_button_seq[].
  124. min = find_sequence(min);
  125. max = find_sequence(max);
  126. uint16_t bitmap = 0;
  127. for(uint16_t i = min; i < max; ++i) {
  128. uint8_t digit = (words_button_seq[i].sequence / divider) % 10;
  129. bitmap |= 1 << (digit - 1);
  130. }
  131. return bitmap;
  132. }