diff --git a/rpcs3/Crypto/utils.cpp b/rpcs3/Crypto/utils.cpp index 7c1d1df309..514bf08580 100644 --- a/rpcs3/Crypto/utils.cpp +++ b/rpcs3/Crypto/utils.cpp @@ -24,13 +24,13 @@ // Auxiliary functions (endian swap, xor). // Bytes conversion auxiliary function. -void bytes_to_hex(std::string& hex_str, const unsigned char* data, unsigned int data_length) +void bytes_to_hex(std::string& hex_str, const unsigned char* data, usz data_length) { - size_t str_length = data_length * 2; + const usz str_length = data_length * 2; hex_str.resize(str_length); - for (size_t i = 0; i < str_length; i += 2) + for (usz i = 0; i < str_length; i += 2) { const auto [ptr, err] = std::to_chars(hex_str.data() + i, hex_str.data() + i + 2, *data++, 16); if (err != std::errc()) @@ -49,19 +49,28 @@ void bytes_to_hex(std::string& hex_str, const unsigned char* data, unsigned int } // Hex string conversion auxiliary function. -void hex_to_bytes(unsigned char* data, std::string_view hex_str, unsigned int str_length) +void hex_to_bytes(unsigned char* data, std::string_view hex_str, usz str_length, std::string* error) { - const auto strn_length = (str_length > 0) ? str_length : hex_str.size(); + const usz strn_length = (str_length > 0) ? str_length : hex_str.size(); // Don't convert if the string length is odd. if ((strn_length % 2) == 0) { - for (size_t i = 0; i < strn_length; i += 2) + for (usz i = 0; i < strn_length; i += 2) { const auto [ptr, err] = std::from_chars(hex_str.data() + i, hex_str.data() + i + 2, *data++, 16); if (err != std::errc()) { - fmt::throw_exception("Failed to read hex string: %s", std::make_error_code(err).message()); + std::string msg = fmt::format("Failed to read hex string: %s (hex='%s')", std::make_error_code(err).message(), hex_str); + + if (error) + { + *error = std::move(msg); + } + else + { + fmt::throw_exception("%s", msg); + } } } } diff --git a/rpcs3/Crypto/utils.h b/rpcs3/Crypto/utils.h index 6e8dab9734..88f0d8ce6f 100644 --- a/rpcs3/Crypto/utils.h +++ b/rpcs3/Crypto/utils.h @@ -16,10 +16,10 @@ char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PA std::string sha256_get_hash(const char* data, usz size, bool lower_case); // Bytes conversion auxiliary function. -void bytes_to_hex(std::string& hex_str, const unsigned char* data, unsigned int data_length); +void bytes_to_hex(std::string& hex_str, const unsigned char* data, usz data_length); // Hex string conversion auxiliary function. -void hex_to_bytes(unsigned char* data, std::string_view hex_str, unsigned int str_length); +void hex_to_bytes(unsigned char* data, std::string_view hex_str, usz str_length, std::string* error = nullptr); // Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC). void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len); diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index 96d196d670..4bd2050638 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -213,25 +213,32 @@ iso_type_status iso_file_decryption::get_key(const std::string& key_path, aes_co return iso_type_status::ERROR_OPENING_KEY; } - char key_str[32]; + std::array key_str {}; std::array key {}; - const u64 key_len = key_file.read(key_str, sizeof(key_str)); + const u64 key_len = key_file.read(key_str.data(), key_str.size()); - if (key_len == sizeof(key_str) || key_len == sizeof(key)) + if (key_len == key_str.size() || key_len == key.size()) { // If the key read from the key file is 16 bytes long instead of 32, consider the file as // binary (".key") and so not needing any further conversion from hex string to bytes - if (key_len == sizeof(key)) + if (key_len == key.size()) { - std::memcpy(key.data(), key_str, sizeof(key)); + std::memcpy(key.data(), key_str.data(), key.size()); } else { - hex_to_bytes(key.data(), std::string_view(key_str, key_len), static_cast(key_len)); + std::string error; + hex_to_bytes(key.data(), std::string_view(key_str.data(), key_str.size()), key_str.size(), &error); + + if (!error.empty()) + { + iso_log.error("get_key(%s): %s", key_path, error); + return iso_type_status::ERROR_PROCESSING_KEY; + } } - aes_context aes_dec; + aes_context aes_dec {}; // If "aes_ctx" not requested if (!aes_ctx)