diff options
| author | 2018-08-04 14:33:11 -0400 | |
|---|---|---|
| committer | 2018-08-04 14:33:11 -0400 | |
| commit | 2b06301dbfbfe79687219bf7783a6d1b47695401 (patch) | |
| tree | 222cc27ecbc7f7e86d2edef8d36436600dee7d7a /src/core/crypto/aes_util.cpp | |
| parent | Merge pull request #919 from lioncash/sign (diff) | |
| parent | Add missing parameter to files.push_back() (diff) | |
| download | yuzu-2b06301dbfbfe79687219bf7783a6d1b47695401.tar.gz yuzu-2b06301dbfbfe79687219bf7783a6d1b47695401.tar.xz yuzu-2b06301dbfbfe79687219bf7783a6d1b47695401.zip | |
Merge pull request #849 from DarkLordZach/xci
XCI and Encrypted NCA Support
Diffstat (limited to 'src/core/crypto/aes_util.cpp')
| -rw-r--r-- | src/core/crypto/aes_util.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp new file mode 100644 index 000000000..4690af5f8 --- /dev/null +++ b/src/core/crypto/aes_util.cpp | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <mbedtls/cipher.h> | ||
| 6 | #include "core/crypto/aes_util.h" | ||
| 7 | #include "core/crypto/key_manager.h" | ||
| 8 | |||
| 9 | namespace Core::Crypto { | ||
| 10 | |||
| 11 | static_assert(static_cast<size_t>(Mode::CTR) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_CTR), | ||
| 12 | "CTR has incorrect value."); | ||
| 13 | static_assert(static_cast<size_t>(Mode::ECB) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_ECB), | ||
| 14 | "ECB has incorrect value."); | ||
| 15 | static_assert(static_cast<size_t>(Mode::XTS) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_XTS), | ||
| 16 | "XTS has incorrect value."); | ||
| 17 | |||
| 18 | // Structure to hide mbedtls types from header file | ||
| 19 | struct CipherContext { | ||
| 20 | mbedtls_cipher_context_t encryption_context; | ||
| 21 | mbedtls_cipher_context_t decryption_context; | ||
| 22 | }; | ||
| 23 | |||
| 24 | template <typename Key, size_t KeySize> | ||
| 25 | Crypto::AESCipher<Key, KeySize>::AESCipher(Key key, Mode mode) | ||
| 26 | : ctx(std::make_unique<CipherContext>()) { | ||
| 27 | mbedtls_cipher_init(&ctx->encryption_context); | ||
| 28 | mbedtls_cipher_init(&ctx->decryption_context); | ||
| 29 | |||
| 30 | ASSERT_MSG((mbedtls_cipher_setup( | ||
| 31 | &ctx->encryption_context, | ||
| 32 | mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode))) || | ||
| 33 | mbedtls_cipher_setup( | ||
| 34 | &ctx->decryption_context, | ||
| 35 | mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode)))) == 0, | ||
| 36 | "Failed to initialize mbedtls ciphers."); | ||
| 37 | |||
| 38 | ASSERT( | ||
| 39 | !mbedtls_cipher_setkey(&ctx->encryption_context, key.data(), KeySize * 8, MBEDTLS_ENCRYPT)); | ||
| 40 | ASSERT( | ||
| 41 | !mbedtls_cipher_setkey(&ctx->decryption_context, key.data(), KeySize * 8, MBEDTLS_DECRYPT)); | ||
| 42 | //"Failed to set key on mbedtls ciphers."); | ||
| 43 | } | ||
| 44 | |||
| 45 | template <typename Key, size_t KeySize> | ||
| 46 | AESCipher<Key, KeySize>::~AESCipher() { | ||
| 47 | mbedtls_cipher_free(&ctx->encryption_context); | ||
| 48 | mbedtls_cipher_free(&ctx->decryption_context); | ||
| 49 | } | ||
| 50 | |||
| 51 | template <typename Key, size_t KeySize> | ||
| 52 | void AESCipher<Key, KeySize>::SetIV(std::vector<u8> iv) { | ||
| 53 | ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, iv.data(), iv.size()) || | ||
| 54 | mbedtls_cipher_set_iv(&ctx->decryption_context, iv.data(), iv.size())) == 0, | ||
| 55 | "Failed to set IV on mbedtls ciphers."); | ||
| 56 | } | ||
| 57 | |||
| 58 | template <typename Key, size_t KeySize> | ||
| 59 | void AESCipher<Key, KeySize>::Transcode(const u8* src, size_t size, u8* dest, Op op) { | ||
| 60 | size_t written = 0; | ||
| 61 | |||
| 62 | const auto context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context; | ||
| 63 | |||
| 64 | mbedtls_cipher_reset(context); | ||
| 65 | |||
| 66 | if (mbedtls_cipher_get_cipher_mode(context) == MBEDTLS_MODE_XTS) { | ||
| 67 | mbedtls_cipher_update(context, src, size, dest, &written); | ||
| 68 | if (written != size) | ||
| 69 | LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.", | ||
| 70 | size, written); | ||
| 71 | } else { | ||
| 72 | const auto block_size = mbedtls_cipher_get_block_size(context); | ||
| 73 | |||
| 74 | for (size_t offset = 0; offset < size; offset += block_size) { | ||
| 75 | auto length = std::min<size_t>(block_size, size - offset); | ||
| 76 | mbedtls_cipher_update(context, src + offset, length, dest + offset, &written); | ||
| 77 | if (written != length) | ||
| 78 | LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.", | ||
| 79 | length, written); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | mbedtls_cipher_finish(context, nullptr, nullptr); | ||
| 84 | } | ||
| 85 | |||
| 86 | template <typename Key, size_t KeySize> | ||
| 87 | void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, size_t size, u8* dest, size_t sector_id, | ||
| 88 | size_t sector_size, Op op) { | ||
| 89 | if (size % sector_size > 0) { | ||
| 90 | LOG_CRITICAL(Crypto, "Data size must be a multiple of sector size."); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | for (size_t i = 0; i < size; i += sector_size) { | ||
| 95 | SetIV(CalculateNintendoTweak(sector_id++)); | ||
| 96 | Transcode<u8, u8>(src + i, sector_size, dest + i, op); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | template <typename Key, size_t KeySize> | ||
| 101 | std::vector<u8> AESCipher<Key, KeySize>::CalculateNintendoTweak(size_t sector_id) { | ||
| 102 | std::vector<u8> out(0x10); | ||
| 103 | for (size_t i = 0xF; i <= 0xF; --i) { | ||
| 104 | out[i] = sector_id & 0xFF; | ||
| 105 | sector_id >>= 8; | ||
| 106 | } | ||
| 107 | return out; | ||
| 108 | } | ||
| 109 | |||
| 110 | template class AESCipher<Key128>; | ||
| 111 | template class AESCipher<Key256>; | ||
| 112 | } // namespace Core::Crypto \ No newline at end of file | ||