Key.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (c) 2018 shchmue
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms and conditions of the GNU General Public License,
  6. * version 2, as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "Key.hpp"
  17. #include <algorithm>
  18. #include <vector>
  19. #include <mbedtls/aes.h>
  20. #include <mbedtls/cmac.h>
  21. #include "Common.hpp"
  22. #include "xxhash64.h"
  23. size_t Key::saved_key_count = 0;
  24. Key::Key(std::string name, u64 xx_hash, byte_vector hash, u8 length, byte_vector key) :
  25. key(key),
  26. name(name),
  27. xx_hash(xx_hash),
  28. hash(hash),
  29. length(length)
  30. {
  31. }
  32. // init with hash only
  33. Key::Key(std::string name, u64 xx_hash, byte_vector hash, u8 length) :
  34. Key(name, xx_hash, hash, length, {})
  35. {
  36. }
  37. // init with key only
  38. Key::Key(std::string name, u8 length, byte_vector key) :
  39. Key(name, {}, {}, length, key)
  40. {
  41. is_found = true;
  42. }
  43. // nameless key
  44. Key::Key(byte_vector key, u8 length) :
  45. Key({}, {}, {}, length, key)
  46. {
  47. is_found = true;
  48. }
  49. // key to be assigned later
  50. Key::Key(std::string name, u8 length) :
  51. Key(name, {}, {}, length, {})
  52. {
  53. }
  54. // declare only
  55. Key::Key() :
  56. Key({}, {}, {}, {}, {})
  57. {
  58. }
  59. void Key::save_key(FILE *file) {
  60. if (!found())
  61. return;
  62. // format: <keyname> = <hex key> for hactool and similar tools
  63. fprintf(file, "%s = ", name.c_str());
  64. for (auto n : key)
  65. fprintf(file, "%02x", n);
  66. fprintf(file, "\n");
  67. saved_key_count++;
  68. }
  69. byte_vector Key::aes_decrypt_ctr(const byte_vector &data, byte_vector iv) {
  70. byte_vector dest(data.size());
  71. if (!found())
  72. return dest;
  73. // used internally
  74. size_t nc_off = 0;
  75. u8 stream_block[0x10];
  76. mbedtls_aes_context dec;
  77. mbedtls_aes_init(&dec);
  78. mbedtls_aes_setkey_enc(&dec, key.data(), length * 8);
  79. mbedtls_aes_crypt_ctr(&dec, data.size(), &nc_off, iv.data(), stream_block, data.data(), dest.data());
  80. mbedtls_aes_free(&dec);
  81. return dest;
  82. }
  83. byte_vector Key::aes_decrypt_ecb(const byte_vector &data) {
  84. byte_vector dest(data.size());
  85. if (!found())
  86. return dest;
  87. mbedtls_aes_context dec;
  88. mbedtls_aes_init(&dec);
  89. mbedtls_aes_setkey_dec(&dec, key.data(), length * 8);
  90. for (size_t offset = 0; offset < data.size(); offset += 0x10)
  91. mbedtls_aes_crypt_ecb(&dec, MBEDTLS_AES_DECRYPT, data.data() + offset, dest.data() + offset);
  92. mbedtls_aes_free(&dec);
  93. return dest;
  94. }
  95. byte_vector Key::cmac(byte_vector data) {
  96. byte_vector dest(data.size());
  97. if (!found())
  98. return dest;
  99. mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB), key.data(), length * 8, data.data(), data.size(), dest.data());
  100. return dest;
  101. }
  102. void Key::find_key(const byte_vector &buffer, size_t start) {
  103. if ((buffer.size() == 0) || (found()))
  104. return;
  105. u8 temp_hash[0x20];
  106. if (buffer.size() == length) {
  107. Common::sha256(buffer.data(), temp_hash, length);
  108. if (!std::equal(hash.begin(), hash.end(), temp_hash))
  109. return;
  110. std::copy(buffer.begin(), buffer.begin() + length, std::back_inserter(key));
  111. is_found = true;
  112. return;
  113. }
  114. // hash every length-sized byte chunk in buffer until it matches member hash
  115. for (size_t i = start; i < buffer.size() - length; i++) {
  116. if (xx_hash == XXHash64::hash(buffer.data() + i, length, 0)) {
  117. // double-check sha256 since xxhash64 isn't as collision-safe
  118. Common::sha256(buffer.data() + i, temp_hash, length);
  119. if (!std::equal(hash.begin(), hash.end(), temp_hash))
  120. continue;
  121. std::copy(buffer.begin() + i, buffer.begin() + i + length, std::back_inserter(key));
  122. is_found = true;
  123. break;
  124. }
  125. }
  126. }
  127. byte_vector Key::generate_kek(Key &master_key, const Key &kek_seed, const Key &key_seed) {
  128. Key kek(master_key.aes_decrypt_ecb(kek_seed.key), 0x10);
  129. Key srcKek(kek.aes_decrypt_ecb(key), 0x10);
  130. if (key_seed.found())
  131. return srcKek.aes_decrypt_ecb(key_seed.key);
  132. else
  133. return srcKek.key;
  134. }