aes_util.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <mbedtls/cipher.h>
  5. #include "common/assert.h"
  6. #include "common/logging/log.h"
  7. #include "core/crypto/aes_util.h"
  8. #include "core/crypto/key_manager.h"
  9. namespace Core::Crypto {
  10. static_assert(static_cast<size_t>(Mode::CTR) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_CTR),
  11. "CTR has incorrect value.");
  12. static_assert(static_cast<size_t>(Mode::ECB) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_ECB),
  13. "ECB has incorrect value.");
  14. static_assert(static_cast<size_t>(Mode::XTS) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_XTS),
  15. "XTS has incorrect value.");
  16. // Structure to hide mbedtls types from header file
  17. struct CipherContext {
  18. mbedtls_cipher_context_t encryption_context;
  19. mbedtls_cipher_context_t decryption_context;
  20. };
  21. template <typename Key, size_t KeySize>
  22. Crypto::AESCipher<Key, KeySize>::AESCipher(Key key, Mode mode)
  23. : ctx(std::make_unique<CipherContext>()) {
  24. mbedtls_cipher_init(&ctx->encryption_context);
  25. mbedtls_cipher_init(&ctx->decryption_context);
  26. ASSERT_MSG((mbedtls_cipher_setup(
  27. &ctx->encryption_context,
  28. mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode))) ||
  29. mbedtls_cipher_setup(
  30. &ctx->decryption_context,
  31. mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode)))) == 0,
  32. "Failed to initialize mbedtls ciphers.");
  33. ASSERT(
  34. !mbedtls_cipher_setkey(&ctx->encryption_context, key.data(), KeySize * 8, MBEDTLS_ENCRYPT));
  35. ASSERT(
  36. !mbedtls_cipher_setkey(&ctx->decryption_context, key.data(), KeySize * 8, MBEDTLS_DECRYPT));
  37. //"Failed to set key on mbedtls ciphers.");
  38. }
  39. template <typename Key, size_t KeySize>
  40. AESCipher<Key, KeySize>::~AESCipher() {
  41. mbedtls_cipher_free(&ctx->encryption_context);
  42. mbedtls_cipher_free(&ctx->decryption_context);
  43. }
  44. template <typename Key, size_t KeySize>
  45. void AESCipher<Key, KeySize>::SetIV(std::vector<u8> iv) {
  46. ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, iv.data(), iv.size()) ||
  47. mbedtls_cipher_set_iv(&ctx->decryption_context, iv.data(), iv.size())) == 0,
  48. "Failed to set IV on mbedtls ciphers.");
  49. }
  50. template <typename Key, size_t KeySize>
  51. void AESCipher<Key, KeySize>::Transcode(const u8* src, size_t size, u8* dest, Op op) const {
  52. auto* const context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context;
  53. mbedtls_cipher_reset(context);
  54. size_t written = 0;
  55. if (mbedtls_cipher_get_cipher_mode(context) == MBEDTLS_MODE_XTS) {
  56. mbedtls_cipher_update(context, src, size, dest, &written);
  57. if (written != size) {
  58. LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.",
  59. size, written);
  60. }
  61. } else {
  62. const auto block_size = mbedtls_cipher_get_block_size(context);
  63. for (size_t offset = 0; offset < size; offset += block_size) {
  64. auto length = std::min<size_t>(block_size, size - offset);
  65. mbedtls_cipher_update(context, src + offset, length, dest + offset, &written);
  66. if (written != length) {
  67. LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.",
  68. length, written);
  69. }
  70. }
  71. }
  72. mbedtls_cipher_finish(context, nullptr, nullptr);
  73. }
  74. template <typename Key, size_t KeySize>
  75. void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, size_t size, u8* dest, size_t sector_id,
  76. size_t sector_size, Op op) {
  77. if (size % sector_size > 0) {
  78. LOG_CRITICAL(Crypto, "Data size must be a multiple of sector size.");
  79. return;
  80. }
  81. for (size_t i = 0; i < size; i += sector_size) {
  82. SetIV(CalculateNintendoTweak(sector_id++));
  83. Transcode<u8, u8>(src + i, sector_size, dest + i, op);
  84. }
  85. }
  86. template <typename Key, size_t KeySize>
  87. std::vector<u8> AESCipher<Key, KeySize>::CalculateNintendoTweak(size_t sector_id) {
  88. std::vector<u8> out(0x10);
  89. for (size_t i = 0xF; i <= 0xF; --i) {
  90. out[i] = sector_id & 0xFF;
  91. sector_id >>= 8;
  92. }
  93. return out;
  94. }
  95. template class AESCipher<Key128>;
  96. template class AESCipher<Key256>;
  97. } // namespace Core::Crypto