├── README.md ├── crypto ├── metadata.h ├── memecrypto.h ├── metadatastringdec.h ├── memecrypto.cpp ├── aes.h ├── metadata.cpp ├── metadatastringdec.cpp └── aes.c ├── tool ├── fileutils.h ├── globalmetadataconverter.h ├── binarywriter.h ├── fileutils.cpp ├── main.cpp ├── globalmetadataconverter.cpp └── globalmetadataformat.h ├── CMakeLists.txt └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # MetadataConverter 2 | 3 | Disclaimer: this is NOT my work! I just took the liberty of publishing it here. 4 | 5 | -------------------------------------------------------------------------------- /crypto/metadata.h: -------------------------------------------------------------------------------- 1 | #ifndef METADATA_H 2 | #define METADATA_H 3 | 4 | #include 5 | #include 6 | 7 | void decrypt_global_metadata(uint8_t *data, size_t size); 8 | void encrypt_global_metadata(uint8_t *data, size_t size); 9 | 10 | #endif //METADATA_H 11 | -------------------------------------------------------------------------------- /tool/fileutils.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEUTILS_H 2 | #define FILEUTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | std::vector read_file(const char *path); 9 | 10 | void write_file(const char *path, const void *buf, size_t size); 11 | 12 | #endif //FILEUTILS_H 13 | -------------------------------------------------------------------------------- /tool/globalmetadataconverter.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBALMETADATACONVERTER_H 2 | #define GLOBALMETADATACONVERTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | std::vector convert_to_unity_global_metadata(uint8_t const *data, size_t len); 9 | 10 | #endif //GLOBALMETADATACONVERTER_H 11 | -------------------------------------------------------------------------------- /crypto/memecrypto.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMECRYPTO_H 2 | #define MEMECRYPTO_H 3 | 4 | #include 5 | 6 | void memecrypto_prepare_key(const uint8_t *in, uint8_t *out); 7 | 8 | void memecrypto_decrypt(const uint8_t *key, uint8_t *data); 9 | 10 | void memecrypto_encrypt(const uint8_t *key, uint8_t *data); 11 | 12 | #endif //MEMECRYPTO_H 13 | -------------------------------------------------------------------------------- /crypto/metadatastringdec.h: -------------------------------------------------------------------------------- 1 | #ifndef METADATASTRINGDEC_H 2 | #define METADATASTRINGDEC_H 3 | 4 | #include 5 | #include 6 | 7 | void recrypt_global_metadata_header_string_fields(uint8_t *data, size_t len, uint8_t *literal_dec_key); 8 | 9 | void recrypt_global_metadata_header_string_literals(uint8_t *data, size_t len, uint8_t *literal_dec_key); 10 | 11 | void generate_key_for_global_metadata_header_string(uint8_t* data, size_t len, uint8_t* literal_dec_key); 12 | 13 | #endif //METADATASTRINGDEC_H 14 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(easydecrypt) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_library(mhycrypto crypto/aes.c crypto/memecrypto.cpp crypto/memecrypto.h crypto/metadata.cpp crypto/metadata.h crypto/metadatastringdec.cpp crypto/metadatastringdec.h) 7 | 8 | add_executable(metadata tool/main.cpp tool/fileutils.cpp tool/fileutils.h tool/binarywriter.h tool/globalmetadataconverter.cpp tool/globalmetadataconverter.h tool/globalmetadataformat.h) 9 | target_link_libraries(metadata PUBLIC mhycrypto) 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> CMake 2 | CMakeLists.txt.user 3 | CMakeCache.txt 4 | CMakeFiles 5 | CMakeScripts 6 | Testing 7 | Makefile 8 | cmake_install.cmake 9 | install_manifest.txt 10 | compile_commands.json 11 | CTestTestfile.cmake 12 | _deps 13 | 14 | # ---> C++ 15 | # Prerequisites 16 | *.d 17 | 18 | # Compiled Object files 19 | *.slo 20 | *.lo 21 | *.o 22 | *.obj 23 | 24 | # Precompiled Headers 25 | *.gch 26 | *.pch 27 | 28 | # Compiled Dynamic libraries 29 | *.so 30 | *.dylib 31 | *.dll 32 | 33 | # Fortran module files 34 | *.mod 35 | *.smod 36 | 37 | # Compiled Static libraries 38 | *.lai 39 | *.la 40 | *.a 41 | *.lib 42 | 43 | # Executables 44 | *.exe 45 | *.out 46 | *.app 47 | 48 | # Build directory 49 | /build/ 50 | -------------------------------------------------------------------------------- /tool/binarywriter.h: -------------------------------------------------------------------------------- 1 | #ifndef BINARYWRITER_H 2 | #define BINARYWRITER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct binary_writer { 9 | 10 | std::vector data; 11 | 12 | void write(const void *ptr, size_t len) { 13 | data.insert(data.end(), (uint8_t *) ptr, (uint8_t *) ptr + len); 14 | } 15 | 16 | template 17 | void write_be(T value) { 18 | uint8_t d[sizeof(value)]; 19 | memcpy(d, &value, sizeof(value)); 20 | for (size_t i = 0; i < sizeof(value) / 2; i++) 21 | std::swap(d[i], d[sizeof(value) - 1 - i]); 22 | write(d, sizeof(value)); 23 | } 24 | 25 | }; 26 | 27 | #endif //BINARYWRITER_H 28 | -------------------------------------------------------------------------------- /tool/fileutils.cpp: -------------------------------------------------------------------------------- 1 | #include "fileutils.h" 2 | 3 | #include 4 | 5 | std::vector read_file(const char *path) { 6 | FILE *f = fopen(path, "rb"); 7 | if (!f) { 8 | fprintf(stderr, "File is missing: %s\n", path); 9 | return std::vector(); 10 | } 11 | fseek(f, 0, SEEK_END); 12 | auto size = ftell(f); 13 | fseek(f, 0, SEEK_SET); 14 | std::vector data; 15 | data.resize(size); 16 | if (fread(data.data(), 1, size, f) != size) 17 | fprintf(stderr, "Read failed (for file at path %s)\n", path); 18 | fclose(f); 19 | return data; 20 | } 21 | 22 | void write_file(const char *path, const void *buf, size_t size) { 23 | FILE *f = fopen(path, "wb"); 24 | if (!f) { 25 | fprintf(stderr, "Could not open file for writing: %s", path); 26 | return; 27 | } 28 | if (fwrite(buf, size, 1, f) != 1) 29 | fprintf(stderr, "Could not write file body: %s [bytes = %lu]", path, size); 30 | fclose(f); 31 | } 32 | -------------------------------------------------------------------------------- /crypto/memecrypto.cpp: -------------------------------------------------------------------------------- 1 | #include "memecrypto.h" 2 | 3 | #include 4 | #include 5 | #include "aes.h" 6 | 7 | static uint8_t dexor16(const uint8_t *c) { 8 | uint8_t ret = 0; 9 | for (int i = 0; i < 16; i++) 10 | ret ^= c[i]; 11 | return ret; 12 | } 13 | 14 | void memecrypto_prepare_key(const uint8_t *in, uint8_t *out) { 15 | for (int i = 0; i < 0xB0; i++) 16 | out[i] = dexor16(&in[0x10 * i]); 17 | } 18 | 19 | extern "C" void oqs_mhy128_enc_c(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext); 20 | extern "C" void oqs_mhy128_dec_c(const uint8_t *ciphertext, const void *_schedule, uint8_t *plaintext); 21 | 22 | void memecrypto_decrypt(const uint8_t *key, uint8_t *data) { 23 | uint8_t plaintext[16]; 24 | oqs_mhy128_enc_c(data, key, plaintext); 25 | memcpy(data, plaintext, 16); 26 | } 27 | 28 | void memecrypto_encrypt(const uint8_t *key, uint8_t *data) { 29 | uint8_t ciphertext[16]; 30 | oqs_mhy128_dec_c(data, key, ciphertext); 31 | memcpy(data, ciphertext, 16); 32 | } 33 | -------------------------------------------------------------------------------- /tool/main.cpp: -------------------------------------------------------------------------------- 1 | #include "fileutils.h" 2 | #include "../crypto/memecrypto.h" 3 | #include "../crypto/metadata.h" 4 | #include "globalmetadataconverter.h" 5 | #include 6 | #include 7 | 8 | void print_help() { 9 | printf("decryptmeta - decrypts global-metadata.dat\n"); 10 | printf("encryptmeta - encrypts global-metadata.dat\n"); 11 | printf("tounitymeta - converts the specified Mihoyo global-metadata.dat file to a standard Unity metadata file\n"); 12 | } 13 | 14 | int main(int argc, char* argv[]) { 15 | if (argc < 2) { 16 | print_help(); 17 | return 0; 18 | } 19 | 20 | if (!strcmp(argv[1], "decryptmeta") && argc >= 4) { 21 | auto fdata = read_file(argv[2]); 22 | decrypt_global_metadata(fdata.data(), fdata.size()); 23 | write_file(argv[3], fdata.data(), fdata.size() - 0x4000); 24 | } else if (!strcmp(argv[1], "encryptmeta") && argc >= 4) { 25 | auto fdata = read_file(argv[2]); 26 | fdata.resize(fdata.size() + 0x4000, 0); 27 | encrypt_global_metadata(fdata.data(), fdata.size()); 28 | write_file(argv[3], fdata.data(), fdata.size()); 29 | } else if (!strcmp(argv[1], "tounitymeta") && argc >= 4) { 30 | auto fdata = read_file(argv[2]); 31 | decrypt_global_metadata(fdata.data(), fdata.size()); 32 | auto unitymeta = convert_to_unity_global_metadata(fdata.data(), fdata.size() - 0x4000); 33 | write_file(argv[3], unitymeta.data(), unitymeta.size()); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /crypto/aes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file aes.h 3 | * \brief Header defining the API for OQS AES 4 | */ 5 | 6 | #ifndef __OQS_AES_H 7 | #define __OQS_AES_H 8 | 9 | #include 10 | #include 11 | 12 | /** 13 | * Function to fill a key schedule given an initial key. 14 | * 15 | * @param key Initial Key. 16 | * @param schedule Abstract data structure for a key schedule. 17 | * @param forEncryption 1 if key schedule is for encryption, 0 if for decryption. 18 | */ 19 | void OQS_AES128_load_schedule(const uint8_t *key, void **schedule, int for_encryption); 20 | 21 | /** 22 | * Function to free a key schedule. 23 | * 24 | * @param schedule Schedule generated with OQS_AES128_load_schedule(). 25 | */ 26 | void OQS_AES128_free_schedule(void *schedule); 27 | 28 | /** 29 | * Function to encrypt blocks of plaintext using ECB mode. 30 | * A schedule based on the key is generated and used internally. 31 | * 32 | * @param plaintext Plaintext to be encrypted. 33 | * @param plaintext_len Length on the plaintext in bytes. Must be a multiple of 16. 34 | * @param key Key to be used for encryption. 35 | * @param ciphertext Pointer to a block of memory which >= in size to the plaintext block. The result will be written here. 36 | */ 37 | void OQS_AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext); 38 | 39 | /** 40 | * Function to decrypt blocks of plaintext using ECB mode. 41 | * A schedule based on the key is generated and used internally. 42 | * 43 | * @param ciphertext Ciphertext to be decrypted. 44 | * @param ciphertext_len Length on the ciphertext in bytes. Must be a multiple of 16. 45 | * @param key Key to be used for encryption. 46 | * @param ciphertext Pointer to a block of memory which >= in size to the ciphertext block. The result will be written here. 47 | */ 48 | void OQS_AES128_ECB_dec(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext); 49 | 50 | /** 51 | * Same as OQS_AES128_ECB_enc() except a schedule generated by 52 | * OQS_AES128_load_schedule() is passed rather then a key. This is faster 53 | * if the same schedule is used for multiple encryptions since it does 54 | * not have to be regenerated from the key. 55 | */ 56 | void OQS_AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext); 57 | 58 | /** 59 | * Same as OQS_AES128_ECB_dec() except a schedule generated by 60 | * OQS_AES128_load_schedule() is passed rather then a key. This is faster 61 | * if the same schedule is used for multiple encryptions since it does 62 | * not have to be regenerated from the key. 63 | */ 64 | void OQS_AES128_ECB_dec_sch(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /crypto/metadata.cpp: -------------------------------------------------------------------------------- 1 | #include "metadata.h" 2 | 3 | #include 4 | #include 5 | #include "memecrypto.h" 6 | #include "metadatastringdec.h" 7 | #include 8 | 9 | unsigned char initial_prev_xor[] = { 0xad, 0x2f, 0x42, 0x30, 0x67, 0x04, 0xb0, 0x9c, 0x9d, 0x2a, 0xc0, 0xba, 0x0e, 0xbf, 0xa5, 0x68 }; 10 | 11 | bool get_global_metadata_keys(uint8_t *src, size_t srcn, uint8_t *longkey, uint8_t *shortkey) { 12 | if (srcn != 0x4000) 13 | return false; 14 | 15 | if (*(uint16_t *) (src + 0xc8) != 0xfc2e || *(uint16_t *) (src + 0xca) != 0x2cfe) 16 | return true; 17 | 18 | auto offB00 = *(uint16_t *) (src + 0xd2); 19 | 20 | for (size_t i = 0; i < 16; i++) 21 | shortkey[i] = src[offB00 + i] ^ src[0x3000 + i]; 22 | 23 | for (size_t i = 0; i < 0xb00; i++) 24 | longkey[i] = src[offB00 + 0x10 + i] ^ src[0x3000 + 0x10 + i] ^ shortkey[i % 16]; 25 | 26 | return true; 27 | } 28 | 29 | bool gen_global_metadata_key(uint8_t* src, size_t srcn) { 30 | if (srcn != 0x4000) 31 | return false; 32 | 33 | #if 0 34 | std::vector read_file(const char* n); 35 | auto data = read_file("xorpad.bin"); 36 | memcpy(src, data.data(), 0x4000); 37 | return false; 38 | #endif 39 | 40 | std::mt19937_64 rand (0xDEADBEEF); 41 | 42 | uint64_t* key = (uint64_t*)src; 43 | 44 | for (int i = 0; i < srcn / sizeof(uint64_t); i++) 45 | key[i] = rand(); 46 | 47 | *(uint16_t *) (src + 0xc8) = 0xfc2e; // Magic 48 | *(uint16_t *) (src + 0xca) = 0x2cfe; // Magic 49 | *(uint16_t *) (src + 0xd2) = rand() & 0x1FFFu; // Just some random value 50 | 51 | return true; 52 | } 53 | 54 | void decrypt_global_metadata(uint8_t *data, size_t size) { 55 | uint8_t longkey[0xB00]; 56 | uint8_t longkeyp[0xB0]; 57 | uint8_t shortkey[16]; 58 | get_global_metadata_keys(data + size - 0x4000, 0x4000, longkey, shortkey); 59 | for (int i = 0; i < 16; i++) 60 | shortkey[i] ^= initial_prev_xor[i]; 61 | memecrypto_prepare_key(longkey, longkeyp); 62 | 63 | auto perentry = (uint32_t) (size / 0x100 / 0x40); 64 | for (int i = 0; i < 0x100; i++) { 65 | auto off = (0x40u * perentry) * i; 66 | 67 | uint8_t prev[16]; 68 | memcpy(prev, shortkey, 16); 69 | for (int j = 0; j < 4; j++) { 70 | uint8_t curr[16]; 71 | memcpy(curr, &data[off + j * 0x10], 16); 72 | 73 | memecrypto_decrypt(longkeyp, curr); 74 | 75 | for (int k = 0; k < 16; k++) 76 | curr[k] ^= prev[k]; 77 | 78 | memcpy(prev, &data[off + j * 0x10], 16); 79 | memcpy(&data[off + j * 0x10], curr, 16); 80 | } 81 | } 82 | 83 | uint8_t literal_dec_key[0x5000]; 84 | recrypt_global_metadata_header_string_fields(data, size, literal_dec_key); 85 | recrypt_global_metadata_header_string_literals(data, size, literal_dec_key); 86 | } 87 | 88 | void encrypt_global_metadata(uint8_t* data, size_t size) { 89 | uint8_t literal_dec_key[0x5000]; 90 | 91 | gen_global_metadata_key(data + size - 0x4000, 0x4000); 92 | 93 | generate_key_for_global_metadata_header_string(data, size, literal_dec_key); 94 | 95 | recrypt_global_metadata_header_string_literals(data, size, literal_dec_key); 96 | recrypt_global_metadata_header_string_fields(data, size, literal_dec_key); 97 | 98 | uint8_t longkey[0xB00]; 99 | uint8_t longkeyp[0xB0]; 100 | uint8_t shortkey[16]; 101 | 102 | get_global_metadata_keys(data + size - 0x4000, 0x4000, longkey, shortkey); 103 | for (int i = 0; i < 16; i++) 104 | shortkey[i] ^= initial_prev_xor[i]; 105 | memecrypto_prepare_key(longkey, longkeyp); 106 | 107 | auto perentry = (uint32_t) (size / 0x100 / 0x40); 108 | for (int i = 0; i < 0x100; i++) { 109 | auto off = (0x40u * perentry) * i; 110 | 111 | uint8_t prev[16]; 112 | memcpy(prev, shortkey, 16); 113 | for (int j = 0; j < 4; j++) { 114 | uint8_t curr[16]; 115 | memcpy(curr, &data[off + j * 0x10], 16); 116 | 117 | for (int k = 0; k < 16; k++) 118 | curr[k] ^= prev[k]; 119 | 120 | memecrypto_encrypt(longkeyp, curr); 121 | 122 | memcpy(prev, curr, 16); 123 | memcpy(&data[off + j * 0x10], curr, 16); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /crypto/metadatastringdec.cpp: -------------------------------------------------------------------------------- 1 | #include "metadatastringdec.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct m_header_fields { 8 | char filler1[0x18]; 9 | uint32_t stringLiteralDataOffset; // 18 10 | uint32_t stringLiteralDataCount; // 1c 11 | uint32_t stringLiteralOffset; // 20 12 | uint32_t stringLiteralCount; // 24 13 | char filler2[0xd8 - 0x28]; 14 | uint32_t stringOffset, stringCount; 15 | }; 16 | 17 | struct m_literal { 18 | uint32_t offset, length; 19 | }; 20 | 21 | void generate_key_for_global_metadata_header_string(uint8_t* data, size_t len, uint8_t* literal_dec_key) { 22 | if (len < sizeof(m_header_fields)) 23 | throw std::out_of_range("data not big enough for global metadata header"); 24 | 25 | uint32_t values[0x12] = { 26 | *(uint32_t *) (data + 0x60), 27 | *(uint32_t *) (data + 0x64), 28 | *(uint32_t *) (data + 0x68), 29 | *(uint32_t *) (data + 0x6c), 30 | *(uint32_t *) (data + 0x140), 31 | *(uint32_t *) (data + 0x144), 32 | *(uint32_t *) (data + 0x148), 33 | *(uint32_t *) (data + 0x14c), 34 | *(uint32_t *) (data + 0x100), 35 | *(uint32_t *) (data + 0x104), 36 | *(uint32_t *) (data + 0x108), 37 | *(uint32_t *) (data + 0x10c), 38 | *(uint32_t *) (data + 0xf0), 39 | *(uint32_t *) (data + 0xf4), 40 | *(uint32_t *) (data + 8), 41 | *(uint32_t *) (data + 0xc), 42 | *(uint32_t *) (data + 0x10), 43 | *(uint32_t *) (data + 0x14) 44 | }; 45 | 46 | uint64_t seed = ((uint64_t) values[values[0] & 0xfu] << 0x20u) | values[(values[0x11] & 0xf) + 2]; 47 | 48 | std::mt19937_64 rand (seed); 49 | 50 | for (int i = 0; i < 6; i++) // Skip 51 | rand(); 52 | 53 | auto key64 = (uint64_t *) literal_dec_key; 54 | for (int i = 0; i < 0xa00; i++) 55 | key64[i] = rand(); 56 | } 57 | 58 | void recrypt_global_metadata_header_string_fields(uint8_t *data, size_t len, uint8_t *literal_dec_key) { 59 | if (len < sizeof(m_header_fields)) 60 | throw std::out_of_range("data not big enough for global metadata header"); 61 | 62 | uint32_t values[0x12] = { 63 | *(uint32_t *) (data + 0x60), 64 | *(uint32_t *) (data + 0x64), 65 | *(uint32_t *) (data + 0x68), 66 | *(uint32_t *) (data + 0x6c), 67 | *(uint32_t *) (data + 0x140), 68 | *(uint32_t *) (data + 0x144), 69 | *(uint32_t *) (data + 0x148), 70 | *(uint32_t *) (data + 0x14c), 71 | *(uint32_t *) (data + 0x100), 72 | *(uint32_t *) (data + 0x104), 73 | *(uint32_t *) (data + 0x108), 74 | *(uint32_t *) (data + 0x10c), 75 | *(uint32_t *) (data + 0xf0), 76 | *(uint32_t *) (data + 0xf4), 77 | *(uint32_t *) (data + 8), 78 | *(uint32_t *) (data + 0xc), 79 | *(uint32_t *) (data + 0x10), 80 | *(uint32_t *) (data + 0x14) 81 | }; 82 | 83 | uint64_t seed = ((uint64_t) values[values[0] & 0xfu] << 0x20u) | values[(values[0x11] & 0xf) + 2]; 84 | 85 | std::mt19937_64 rand (seed); 86 | 87 | auto header = (m_header_fields *) data; 88 | header->stringCount ^= (uint32_t) rand(); 89 | header->stringOffset ^= (uint32_t) rand(); 90 | rand(); 91 | header->stringLiteralOffset ^= (uint32_t) rand(); 92 | header->stringLiteralDataCount ^= (uint32_t) rand(); 93 | header->stringLiteralDataOffset ^= (uint32_t) rand(); 94 | 95 | auto key64 = (uint64_t *) literal_dec_key; 96 | for (int i = 0; i < 0xa00; i++) 97 | key64[i] = rand(); 98 | } 99 | 100 | void recrypt_global_metadata_header_string_literals(uint8_t *data, size_t len, uint8_t *literal_dec_key) { 101 | if (len < sizeof(m_header_fields)) 102 | throw std::out_of_range("data not big enough for global metadata header"); 103 | 104 | auto header = (m_header_fields *) data; 105 | if ((size_t) header->stringLiteralCount + header->stringLiteralOffset > len) 106 | throw std::out_of_range("file trimmed or string literal offset/count field invalid"); 107 | 108 | auto literals = (m_literal *) (data + header->stringLiteralOffset); 109 | auto count = header->stringLiteralCount / sizeof(m_literal); 110 | for (size_t i = 0; i < count; i++) { 111 | auto slen = literals[i].length; 112 | uint8_t *str = data + header->stringLiteralDataOffset + literals[i].offset; 113 | uint8_t *okey = literal_dec_key + (i % 0x2800); 114 | 115 | if ((size_t) header->stringLiteralDataOffset + literals[i].offset + slen > len) 116 | throw std::out_of_range("file trimmed or contains invalid string entry"); 117 | 118 | for (size_t j = 0; j < slen; j++) 119 | str[j] ^= literal_dec_key[(j + 0x1400u) % 0x5000u] ^ (okey[j % 0x2800u] + (uint8_t) j); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /tool/globalmetadataconverter.cpp: -------------------------------------------------------------------------------- 1 | #include "globalmetadataconverter.h" 2 | 3 | #include 4 | #include "binarywriter.h" 5 | #include "globalmetadataformat.h" 6 | 7 | struct converter { 8 | 9 | uint8_t const *src; 10 | size_t src_len; 11 | binary_writer writer; 12 | 13 | converter(uint8_t const *src, size_t src_len) : src(src), src_len(src_len) {} 14 | 15 | template 16 | void allocate_header() { 17 | writer.data.resize(sizeof(Header)); 18 | } 19 | 20 | template 21 | void set_header(Header const &header) { 22 | memcpy(writer.data.data(), &header, sizeof(header)); 23 | } 24 | 25 | void copy_section(uint32_t from_offset, uint32_t from_size, uint32_t &to_offset, uint32_t &to_size) { 26 | if (from_offset > src_len || from_size > src_len - from_offset) 27 | throw std::runtime_error("Section source exceeds source data size"); 28 | to_offset = writer.data.size(); 29 | to_size = from_size; 30 | writer.data.insert(writer.data.end(), src + from_offset, src + from_offset + from_size); 31 | } 32 | 33 | template 34 | void convert_section(uint32_t from_offset, uint32_t from_size, uint32_t &to_offset, uint32_t &to_size) { 35 | if (from_offset > src_len || from_size > src_len - from_offset) 36 | throw std::runtime_error("Section source exceeds source data size"); 37 | if (from_size % sizeof(From) != 0) 38 | throw std::runtime_error("From size should be dividable by the element size"); 39 | size_t count = from_size / sizeof(From); 40 | to_offset = writer.data.size(); 41 | to_size = count * sizeof(To); 42 | if (to_size / sizeof(To) != count) 43 | throw std::runtime_error("Invalid number of elements (too high)"); 44 | writer.data.reserve(writer.data.size() + to_size); 45 | From *from = (From *) &src[from_offset]; 46 | for (size_t i = 0; i < count; i++) { 47 | auto converted = Converter(from[i]); 48 | writer.write(&converted, sizeof(converted)); 49 | } 50 | } 51 | 52 | #if IL2CPP_FORMAT_VERSION >= IL2CPP_GENSHIN_270 53 | void forge_metadata_usage_lists_section(uint32_t pairs_count, uint32_t &to_offset, uint32_t &to_size) { 54 | Il2CppMetadataUsageList list = { 0 }; 55 | list.start = 0; 56 | list.count = pairs_count; 57 | to_offset = writer.data.size(); 58 | to_size = 1 * sizeof(Il2CppMetadataUsageList); 59 | writer.data.reserve(writer.data.size() + to_size); 60 | writer.write(&list, sizeof(Il2CppMetadataUsageList)); 61 | } 62 | #endif 63 | }; 64 | 65 | 66 | std::vector convert_to_unity_global_metadata(uint8_t const *data, size_t len) { 67 | converter cv (data, len); 68 | auto const &srch = *(Il2CppGlobalMetadataHeaderMihoyo *) data; 69 | Il2CppGlobalMetadataHeader outh {}; 70 | outh.sanity = 0xfab11baf; 71 | outh.version = 24; 72 | cv.allocate_header(); 73 | cv.convert_section(srch.stringLiteralOffset, srch.stringLiteralCount, outh.stringLiteralOffset, outh.stringLiteralCount); 74 | cv.copy_section(srch.stringLiteralDataOffset, srch.stringLiteralDataCount, outh.stringLiteralDataOffset, outh.stringLiteralDataCount); 75 | cv.copy_section(srch.stringOffset, srch.stringCount, outh.stringOffset, outh.stringCount); 76 | cv.copy_section(srch.eventsOffset, srch.eventsCount, outh.eventsOffset, outh.eventsCount); 77 | cv.convert_section(srch.propertiesOffset, srch.propertiesCount, outh.propertiesOffset, outh.propertiesCount); 78 | cv.convert_section(srch.methodsOffset, srch.methodsCount, outh.methodsOffset, outh.methodsCount); 79 | cv.copy_section(srch.parameterDefaultValuesOffset, srch.parameterDefaultValuesCount, outh.parameterDefaultValuesOffset, outh.parameterDefaultValuesCount); 80 | cv.copy_section(srch.fieldDefaultValuesOffset, srch.fieldDefaultValuesCount, outh.fieldDefaultValuesOffset, outh.fieldDefaultValuesCount); 81 | cv.copy_section(srch.fieldAndParameterDefaultValueDataOffset, srch.fieldAndParameterDefaultValueDataCount, outh.fieldAndParameterDefaultValueDataOffset, outh.fieldAndParameterDefaultValueDataCount); 82 | cv.copy_section(srch.fieldMarshaledSizesOffset, srch.fieldMarshaledSizesCount, outh.fieldMarshaledSizesOffset, outh.fieldMarshaledSizesCount); 83 | cv.copy_section(srch.parametersOffset, srch.parametersCount, outh.parametersOffset, outh.parametersCount); 84 | cv.convert_section(srch.fieldsOffset, srch.fieldsCount, outh.fieldsOffset, outh.fieldsCount); 85 | cv.copy_section(srch.genericParametersOffset, srch.genericParametersCount, outh.genericParametersOffset, outh.genericParametersCount); 86 | cv.copy_section(srch.genericParameterConstraintsOffset, srch.genericParameterConstraintsCount, outh.genericParameterConstraintsOffset, outh.genericParameterConstraintsCount); 87 | cv.copy_section(srch.genericContainersOffset, srch.genericContainersCount, outh.genericContainersOffset, outh.genericContainersCount); 88 | cv.copy_section(srch.nestedTypesOffset, srch.nestedTypesCount, outh.nestedTypesOffset, outh.nestedTypesCount); 89 | cv.copy_section(srch.interfacesOffset, srch.interfacesCount, outh.interfacesOffset, outh.interfacesCount); 90 | cv.copy_section(srch.vtableMethodsOffset, srch.vtableMethodsCount, outh.vtableMethodsOffset, outh.vtableMethodsCount); 91 | cv.copy_section(srch.interfaceOffsetsOffset, srch.interfaceOffsetsCount, outh.interfaceOffsetsOffset, outh.interfaceOffsetsCount); 92 | cv.convert_section(srch.typeDefinitionsOffset, srch.typeDefinitionsCount, outh.typeDefinitionsOffset, outh.typeDefinitionsCount); 93 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 94 | cv.copy_section(srch.rgctxEntriesOffset, srch.rgctxEntriesCount, outh.rgctxEntriesOffset, outh.rgctxEntriesCount); 95 | #endif 96 | cv.copy_section(srch.imagesOffset, srch.imagesCount, outh.imagesOffset, outh.imagesCount); 97 | cv.copy_section(srch.assembliesOffset, srch.assembliesCount, outh.assembliesOffset, outh.assembliesCount); 98 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 99 | cv.copy_section(srch.metadataUsageListsOffset, srch.metadataUsageListsCount, outh.metadataUsageListsOffset, outh.metadataUsageListsCount); 100 | #else 101 | cv.forge_metadata_usage_lists_section(srch.metadataUsagePairsCount / sizeof(Il2CppMetadataUsagePair), outh.metadataUsageListsOffset, outh.metadataUsageListsCount); 102 | #endif 103 | cv.copy_section(srch.metadataUsagePairsOffset, srch.metadataUsagePairsCount, outh.metadataUsagePairsOffset, outh.metadataUsagePairsCount); 104 | cv.copy_section(srch.fieldRefsOffset, srch.fieldRefsCount, outh.fieldRefsOffset, outh.fieldRefsCount); 105 | cv.copy_section(srch.referencedAssembliesOffset, srch.referencedAssembliesCount, outh.referencedAssembliesOffset, outh.referencedAssembliesCount); 106 | cv.copy_section(srch.attributesInfoOffset, srch.attributesInfoCount, outh.attributesInfoOffset, outh.attributesInfoCount); 107 | cv.copy_section(srch.attributeTypesOffset, srch.attributeTypesCount, outh.attributeTypesOffset, outh.attributeTypesCount); 108 | cv.copy_section(srch.unresolvedVirtualCallParameterTypesOffset, srch.unresolvedVirtualCallParameterTypesCount, outh.unresolvedVirtualCallParameterTypesOffset, outh.unresolvedVirtualCallParameterTypesCount); 109 | cv.copy_section(srch.unresolvedVirtualCallParameterRangesOffset, srch.unresolvedVirtualCallParameterRangesCount, outh.unresolvedVirtualCallParameterRangesOffset, outh.unresolvedVirtualCallParameterRangesCount); 110 | cv.copy_section(srch.windowsRuntimeTypeNamesOffset, srch.windowsRuntimeTypeNamesSize, outh.windowsRuntimeTypeNamesOffset, outh.windowsRuntimeTypeNamesSize); 111 | cv.copy_section(srch.exportedTypeDefinitionsOffset, srch.exportedTypeDefinitionsCount, outh.exportedTypeDefinitionsOffset, outh.exportedTypeDefinitionsCount); 112 | cv.set_header(outh); 113 | return cv.writer.data; 114 | } 115 | -------------------------------------------------------------------------------- /tool/globalmetadataformat.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBALMETADATAFORMAT_H 2 | #define GLOBALMETADATAFORMAT_H 3 | 4 | #define IL2CPP_GENSHIN_270 2440 // 24.4 ? 5 | #define IL2CPP_GENSHIN_100 2400 // 24.0 ? 6 | 7 | //#define IL2CPP_FORMAT_VERSION IL2CPP_GENSHIN_100 8 | #define IL2CPP_FORMAT_VERSION IL2CPP_GENSHIN_270 9 | 10 | /* Non-Mihoyo Global Metadata format */ 11 | struct Il2CppGlobalMetadataHeader { 12 | uint32_t sanity; 13 | uint32_t version; 14 | uint32_t stringLiteralOffset; 15 | uint32_t stringLiteralCount; 16 | uint32_t stringLiteralDataOffset; 17 | uint32_t stringLiteralDataCount; 18 | uint32_t stringOffset; 19 | uint32_t stringCount; 20 | uint32_t eventsOffset; 21 | uint32_t eventsCount; 22 | uint32_t propertiesOffset; 23 | uint32_t propertiesCount; 24 | uint32_t methodsOffset; 25 | uint32_t methodsCount; 26 | uint32_t parameterDefaultValuesOffset; 27 | uint32_t parameterDefaultValuesCount; 28 | uint32_t fieldDefaultValuesOffset; 29 | uint32_t fieldDefaultValuesCount; 30 | uint32_t fieldAndParameterDefaultValueDataOffset; 31 | uint32_t fieldAndParameterDefaultValueDataCount; 32 | uint32_t fieldMarshaledSizesOffset; 33 | uint32_t fieldMarshaledSizesCount; 34 | uint32_t parametersOffset; 35 | uint32_t parametersCount; 36 | uint32_t fieldsOffset; 37 | uint32_t fieldsCount; 38 | uint32_t genericParametersOffset; 39 | uint32_t genericParametersCount; 40 | uint32_t genericParameterConstraintsOffset; 41 | uint32_t genericParameterConstraintsCount; 42 | uint32_t genericContainersOffset; 43 | uint32_t genericContainersCount; 44 | uint32_t nestedTypesOffset; 45 | uint32_t nestedTypesCount; 46 | uint32_t interfacesOffset; 47 | uint32_t interfacesCount; 48 | uint32_t vtableMethodsOffset; 49 | uint32_t vtableMethodsCount; 50 | uint32_t interfaceOffsetsOffset; 51 | uint32_t interfaceOffsetsCount; 52 | uint32_t typeDefinitionsOffset; 53 | uint32_t typeDefinitionsCount; 54 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 55 | uint32_t rgctxEntriesOffset; 56 | uint32_t rgctxEntriesCount; 57 | #endif 58 | uint32_t imagesOffset; 59 | uint32_t imagesCount; 60 | uint32_t assembliesOffset; 61 | uint32_t assembliesCount; 62 | uint32_t metadataUsageListsOffset; 63 | uint32_t metadataUsageListsCount; 64 | uint32_t metadataUsagePairsOffset; 65 | uint32_t metadataUsagePairsCount; 66 | uint32_t fieldRefsOffset; 67 | uint32_t fieldRefsCount; 68 | uint32_t referencedAssembliesOffset; 69 | uint32_t referencedAssembliesCount; 70 | uint32_t attributesInfoOffset; 71 | uint32_t attributesInfoCount; 72 | uint32_t attributeTypesOffset; 73 | uint32_t attributeTypesCount; 74 | uint32_t unresolvedVirtualCallParameterTypesOffset; 75 | uint32_t unresolvedVirtualCallParameterTypesCount; 76 | uint32_t unresolvedVirtualCallParameterRangesOffset; 77 | uint32_t unresolvedVirtualCallParameterRangesCount; 78 | uint32_t windowsRuntimeTypeNamesOffset; 79 | uint32_t windowsRuntimeTypeNamesSize; 80 | uint32_t exportedTypeDefinitionsOffset; 81 | uint32_t exportedTypeDefinitionsCount; 82 | }; 83 | 84 | struct Il2CppStringLiteral { 85 | uint32_t length; 86 | uint32_t dataIndex; 87 | }; 88 | 89 | struct Il2CppPropertyDefinition { 90 | uint32_t nameIndex; 91 | uint32_t get; 92 | uint32_t set; 93 | uint32_t attrs; 94 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 95 | uint32_t customAttributeIndex; 96 | #endif 97 | uint32_t token; 98 | }; 99 | 100 | struct Il2CppMethodDefinition { 101 | uint32_t nameIndex; 102 | uint32_t declaringType; 103 | uint32_t returnType; 104 | uint32_t parameterStart; 105 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 106 | uint32_t customAttributeIndex; 107 | #endif 108 | uint32_t genericContainerIndex; 109 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 110 | uint32_t methodIndex; 111 | uint32_t invokerIndex; 112 | uint32_t reversePInvokeWrapperIndex; 113 | uint32_t rgctxStartIndex; 114 | uint32_t rgctxCount; 115 | #endif 116 | uint32_t token; 117 | uint16_t flags; 118 | uint16_t iflags; 119 | uint16_t slot; 120 | uint16_t parameterCount; 121 | }; 122 | 123 | struct Il2CppFieldDefinition { 124 | uint32_t nameIndex; 125 | uint32_t typeIndex; 126 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 127 | uint32_t customAttributeIndex; 128 | #endif 129 | uint32_t token; 130 | }; 131 | 132 | struct Il2CppTypeDefinition { 133 | uint32_t nameIndex; 134 | uint32_t namespaceIndex; 135 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 136 | uint32_t customAttributeIndex; 137 | #endif 138 | uint32_t byvalTypeIndex; 139 | uint32_t byrefTypeIndex; 140 | uint32_t declaringTypeIndex; 141 | uint32_t parentIndex; 142 | uint32_t elementTypeIndex; 143 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 144 | uint32_t rgctxStartIndex; 145 | uint32_t rgctxCount; 146 | #endif 147 | uint32_t genericContainerIndex; 148 | uint32_t flags; 149 | uint32_t fieldStart; 150 | uint32_t methodStart; 151 | uint32_t eventStart; 152 | uint32_t propertyStart; 153 | uint32_t nestedTypesStart; 154 | uint32_t interfacesStart; 155 | uint32_t vtableStart; 156 | uint32_t interfaceOffsetsStart; 157 | uint16_t method_count; 158 | uint16_t property_count; 159 | uint16_t field_count; 160 | uint16_t event_count; 161 | uint16_t nested_type_count; 162 | uint16_t vtable_count; 163 | uint16_t interfaces_count; 164 | uint16_t interface_offsets_count; 165 | uint32_t bitfield; 166 | uint32_t token; 167 | }; 168 | 169 | struct Il2CppMetadataUsageList 170 | { 171 | uint32_t start; 172 | uint32_t count; 173 | }; 174 | 175 | struct Il2CppMetadataUsagePair 176 | { 177 | uint32_t destinationIndex; 178 | uint32_t encodedSourceIndex; 179 | }; 180 | 181 | /* Mihoyo Global Metadata format (with shuffled fields) */ 182 | 183 | struct Il2CppGlobalMetadataHeaderMihoyo { 184 | uint32_t filler00; 185 | uint32_t filler04; 186 | uint32_t filler08; 187 | uint32_t filler0C; 188 | uint32_t filler10; 189 | uint32_t filler14; 190 | uint32_t stringLiteralDataOffset; // 18 191 | uint32_t stringLiteralDataCount; // 1C 192 | uint32_t stringLiteralOffset; // 20 193 | uint32_t stringLiteralCount; // 24 194 | uint32_t genericContainersOffset; // 28 195 | uint32_t genericContainersCount; // 2C 196 | uint32_t nestedTypesOffset; // 30 197 | uint32_t nestedTypesCount; // 34 198 | uint32_t interfacesOffset; // 38 199 | uint32_t interfacesCount; // 3C 200 | uint32_t vtableMethodsOffset; // 40 201 | uint32_t vtableMethodsCount; // 44 202 | uint32_t interfaceOffsetsOffset; // 48 203 | uint32_t interfaceOffsetsCount; // 4C 204 | uint32_t typeDefinitionsOffset; // 50 205 | uint32_t typeDefinitionsCount; // 54 206 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 207 | uint32_t rgctxEntriesOffset; // 58 208 | uint32_t rgctxEntriesCount; // 5C 209 | #else 210 | uint32_t filler58; // TODO: Unknown! 211 | uint32_t filler5C; // TODO: Unknown! 212 | #endif 213 | uint32_t filler60; 214 | uint32_t filler64; 215 | uint32_t filler68; 216 | uint32_t filler6C; 217 | uint32_t imagesOffset; // 70 218 | uint32_t imagesCount; // 74 219 | uint32_t assembliesOffset; // 78 220 | uint32_t assembliesCount; // 7C 221 | uint32_t fieldsOffset; // 80 222 | uint32_t fieldsCount; // 84 223 | uint32_t genericParametersOffset; // 88 224 | uint32_t genericParametersCount; // 8C 225 | uint32_t fieldAndParameterDefaultValueDataOffset; // 90 226 | uint32_t fieldAndParameterDefaultValueDataCount; // 94 227 | uint32_t fieldMarshaledSizesOffset; // 98 228 | uint32_t fieldMarshaledSizesCount; // 9C 229 | uint32_t referencedAssembliesOffset; // A0 230 | uint32_t referencedAssembliesCount; // A4 231 | uint32_t attributesInfoOffset; // A8 232 | uint32_t attributesInfoCount; // AC 233 | uint32_t attributeTypesOffset; // B0 234 | uint32_t attributeTypesCount; // B4 235 | uint32_t unresolvedVirtualCallParameterTypesOffset; // B8 236 | uint32_t unresolvedVirtualCallParameterTypesCount; // BC 237 | uint32_t unresolvedVirtualCallParameterRangesOffset; // C0 238 | uint32_t unresolvedVirtualCallParameterRangesCount; // C4 239 | uint32_t windowsRuntimeTypeNamesOffset; // C8 240 | uint32_t windowsRuntimeTypeNamesSize; // CC 241 | uint32_t exportedTypeDefinitionsOffset; // D0 242 | uint32_t exportedTypeDefinitionsCount; // D4 243 | uint32_t stringOffset; // D8 244 | uint32_t stringCount; // DC 245 | uint32_t parametersOffset; // E0 246 | uint32_t parametersCount; // E4 247 | uint32_t genericParameterConstraintsOffset; // E8 248 | uint32_t genericParameterConstraintsCount; // EC 249 | uint32_t fillerF0; 250 | uint32_t fillerF4; 251 | uint32_t metadataUsagePairsOffset; // F8 252 | uint32_t metadataUsagePairsCount; // FC 253 | uint32_t filler100; 254 | uint32_t filler104; 255 | uint32_t filler108; 256 | uint32_t filler10C; 257 | uint32_t fieldRefsOffset; // 110 258 | uint32_t fieldRefsCount; // 114 259 | uint32_t eventsOffset; // 118 260 | uint32_t eventsCount; // 11C 261 | uint32_t propertiesOffset; // 120 262 | uint32_t propertiesCount; // 124 263 | uint32_t methodsOffset; // 128 264 | uint32_t methodsCount; // 12C 265 | uint32_t parameterDefaultValuesOffset; // 130 266 | uint32_t parameterDefaultValuesCount; // 134 267 | uint32_t fieldDefaultValuesOffset; // 138 268 | uint32_t fieldDefaultValuesCount; // 13C 269 | uint32_t filler140; 270 | uint32_t filler144; 271 | uint32_t filler148; 272 | uint32_t filler14C; 273 | uint32_t metadataUsageListsOffset; // 150 274 | uint32_t metadataUsageListsCount; // 154 275 | }; 276 | 277 | struct Il2CppStringLiteralMihoyo { 278 | uint32_t dataIndex; 279 | uint32_t length; 280 | }; 281 | 282 | struct Il2CppPropertyDefinitionMihoyo { 283 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 284 | uint32_t customAttributeIndex; 285 | #endif 286 | uint32_t nameIndex; 287 | uint32_t filler08; 288 | uint32_t token; 289 | uint32_t attrs; 290 | uint32_t filler14; 291 | uint32_t set; 292 | uint32_t get; 293 | }; 294 | 295 | struct Il2CppMethodDefinitionMihoyo { 296 | uint32_t returnType; 297 | uint32_t declaringType; 298 | uint32_t filler08; 299 | uint32_t nameIndex; 300 | uint32_t parameterStart; 301 | uint32_t genericContainerIndex; 302 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 303 | uint32_t customAttributeIndex; 304 | uint32_t reversePInvokeWrapperIndex; 305 | #endif 306 | uint32_t filler20; 307 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 308 | uint32_t methodIndex; 309 | uint32_t invokerIndex; 310 | uint32_t rgctxCount; 311 | uint32_t rgctxStartIndex; 312 | #endif 313 | uint16_t parameterCount; 314 | uint16_t flags; 315 | uint16_t slot; 316 | uint16_t iflags; 317 | uint32_t token; 318 | }; 319 | 320 | struct Il2CppFieldDefinitionMihoyo { 321 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 322 | uint32_t customAttributeIndex; 323 | #endif 324 | uint32_t typeIndex; 325 | uint32_t nameIndex; 326 | uint32_t token; 327 | }; 328 | 329 | struct Il2CppTypeDefinitionMihoyo { 330 | uint32_t nameIndex; 331 | uint32_t namespaceIndex; 332 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 333 | uint32_t customAttributeIndex; 334 | #endif 335 | uint32_t byvalTypeIndex; 336 | uint32_t byrefTypeIndex; 337 | uint32_t declaringTypeIndex; 338 | uint32_t parentIndex; 339 | uint32_t elementTypeIndex; 340 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 341 | uint32_t rgctxStartIndex; 342 | uint32_t rgctxCount; 343 | #endif 344 | uint32_t genericContainerIndex; 345 | uint32_t flags; 346 | uint32_t fieldStart; 347 | uint32_t propertyStart; 348 | uint32_t methodStart; 349 | uint32_t eventStart; 350 | uint32_t nestedTypesStart; 351 | uint32_t interfacesStart; 352 | uint32_t interfaceOffsetsStart; 353 | uint32_t vtableStart; 354 | uint16_t event_count; 355 | uint16_t method_count; 356 | uint16_t property_count; 357 | uint16_t field_count; 358 | uint16_t vtable_count; 359 | uint16_t interfaces_count; 360 | uint16_t interface_offsets_count; 361 | uint16_t nested_type_count; 362 | uint32_t bitfield; 363 | uint32_t token; 364 | }; 365 | 366 | 367 | /* Conversion functions */ 368 | 369 | template 370 | static inline To convert_Il2CppStringLiteral(From from) { 371 | To to {}; 372 | to.length = from.length; 373 | to.dataIndex = from.dataIndex; 374 | return to; 375 | } 376 | 377 | template 378 | static inline To convert_Il2CppPropertyDefinition(From from) { 379 | To to {}; 380 | to.nameIndex = from.nameIndex; 381 | to.get = from.get; 382 | to.set = from.set; 383 | to.attrs = from.attrs; 384 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 385 | to.customAttributeIndex = from.customAttributeIndex; 386 | #endif 387 | to.token = from.token; 388 | return to; 389 | } 390 | 391 | template 392 | static inline To convert_Il2CppMethodDefinition(From from) { 393 | To to {}; 394 | to.nameIndex = from.nameIndex; 395 | to.declaringType = from.declaringType; 396 | to.returnType = from.returnType; 397 | to.parameterStart = from.parameterStart; 398 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 399 | to.customAttributeIndex = from.customAttributeIndex; 400 | #endif 401 | to.genericContainerIndex = from.genericContainerIndex; 402 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 403 | to.methodIndex = from.methodIndex; 404 | to.invokerIndex = from.invokerIndex; 405 | to.reversePInvokeWrapperIndex = from.reversePInvokeWrapperIndex; 406 | to.rgctxStartIndex = from.rgctxStartIndex; 407 | to.rgctxCount = from.rgctxCount; 408 | #endif 409 | to.token = from.token; 410 | to.flags = from.flags; 411 | to.iflags = from.iflags; 412 | to.slot = from.slot; 413 | to.parameterCount = from.parameterCount; 414 | return to; 415 | } 416 | 417 | template 418 | static inline To convert_Il2CppFieldDefinition(From from) { 419 | To to {}; 420 | to.nameIndex = from.nameIndex; 421 | to.typeIndex = from.typeIndex; 422 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 423 | to.customAttributeIndex = from.customAttributeIndex; 424 | #endif 425 | to.token = from.token; 426 | return to; 427 | } 428 | 429 | template 430 | static inline To convert_Il2CppTypeDefinition(From from) { 431 | To to {}; 432 | to.nameIndex = from.nameIndex; 433 | to.namespaceIndex = from.namespaceIndex; 434 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 435 | to.customAttributeIndex = from.customAttributeIndex; 436 | #endif 437 | to.byvalTypeIndex = from.byvalTypeIndex; 438 | to.byrefTypeIndex = from.byrefTypeIndex; 439 | to.declaringTypeIndex = from.declaringTypeIndex; 440 | to.parentIndex = from.parentIndex; 441 | to.elementTypeIndex = from.elementTypeIndex; 442 | #if IL2CPP_FORMAT_VERSION < IL2CPP_GENSHIN_270 443 | to.rgctxStartIndex = from.rgctxStartIndex; 444 | to.rgctxCount = from.rgctxCount; 445 | #endif 446 | to.genericContainerIndex = from.genericContainerIndex; 447 | to.flags = from.flags; 448 | to.fieldStart = from.fieldStart; 449 | to.methodStart = from.methodStart; 450 | to.eventStart = from.eventStart; 451 | to.propertyStart = from.propertyStart; 452 | to.nestedTypesStart = from.nestedTypesStart; 453 | to.interfacesStart = from.interfacesStart; 454 | to.vtableStart = from.vtableStart; 455 | to.interfaceOffsetsStart = from.interfaceOffsetsStart; 456 | to.method_count = from.method_count; 457 | to.property_count = from.property_count; 458 | to.field_count = from.field_count; 459 | to.event_count = from.event_count; 460 | to.nested_type_count = from.nested_type_count; 461 | to.vtable_count = from.vtable_count; 462 | to.interfaces_count = from.interfaces_count; 463 | to.interface_offsets_count = from.interface_offsets_count; 464 | to.bitfield = from.bitfield; 465 | to.token = from.token; 466 | return to; 467 | } 468 | 469 | #endif 470 | -------------------------------------------------------------------------------- /crypto/aes.c: -------------------------------------------------------------------------------- 1 | // Simple, thoroughly commented implementation of 128-bit AES / Rijndael using C 2 | // Chris Hulbert - chris.hulbert@gmail.com - http://splinter.com.au/blog 3 | // References: 4 | // http://en.wikipedia.org/wiki/Advanced_Encryption_Standard 5 | // http://en.wikipedia.org/wiki/Rijndael_key_schedule 6 | // http://en.wikipedia.org/wiki/Rijndael_mix_columns 7 | // http://en.wikipedia.org/wiki/Rijndael_S-box 8 | // This code is public domain, or any OSI-approved license, your choice. No warranty. 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "aes.h" 15 | 16 | typedef unsigned char byte; 17 | 18 | // Here are all the lookup tables for the row shifts, rcon, s-boxes, and galois field multiplications 19 | static const byte shift_rows_table[] = {0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11}; 20 | static const byte shift_rows_table_inv[] = {0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3}; 21 | static const byte lookup_rcon[] = { 22 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a}; 23 | static const byte lookup_sbox[] = { 24 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 25 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 26 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 27 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 28 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 29 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 30 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 31 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 32 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 33 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 34 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 35 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 36 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 37 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 38 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 39 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; 40 | static const byte lookup_sbox_inv[] = { 41 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 42 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 43 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 44 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 45 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 46 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 47 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 48 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 49 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 50 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 51 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 52 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 53 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 54 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 55 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 56 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; 57 | static const byte lookup_g2[] = { 58 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 59 | 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 60 | 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 61 | 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 62 | 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 63 | 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 64 | 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, 65 | 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 66 | 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, 67 | 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, 68 | 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 69 | 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, 70 | 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, 71 | 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 72 | 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, 73 | 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5}; 74 | static const byte lookup_g3[] = { 75 | 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, 76 | 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 77 | 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, 78 | 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, 79 | 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 80 | 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, 81 | 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, 82 | 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 83 | 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, 84 | 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, 85 | 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, 86 | 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, 87 | 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, 88 | 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, 89 | 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, 90 | 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a}; 91 | static const byte lookup_g9[] = { 92 | 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 93 | 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 94 | 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 95 | 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, 96 | 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 97 | 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, 98 | 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, 99 | 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 100 | 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, 101 | 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, 102 | 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 103 | 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 104 | 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, 105 | 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 106 | 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, 107 | 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46}; 108 | static const byte lookup_g11[] = { 109 | 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 110 | 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 111 | 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, 112 | 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, 113 | 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 114 | 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, 115 | 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, 116 | 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 117 | 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, 118 | 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, 119 | 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 120 | 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, 121 | 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 122 | 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 123 | 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, 124 | 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3}; 125 | static const byte lookup_g13[] = { 126 | 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 127 | 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 128 | 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, 129 | 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, 130 | 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 131 | 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 132 | 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, 133 | 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 134 | 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, 135 | 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 136 | 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 137 | 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, 138 | 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, 139 | 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 140 | 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, 141 | 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97}; 142 | static const byte lookup_g14[] = { 143 | 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 144 | 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 145 | 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, 146 | 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, 147 | 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 148 | 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, 149 | 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, 150 | 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 151 | 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 152 | 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 153 | 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 154 | 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 155 | 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 156 | 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 157 | 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, 158 | 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d}; 159 | 160 | // Xor's all elements in a n byte array a by b 161 | static void xor (byte * a, const byte *b, int n) { 162 | int i; 163 | for (i = 0; i < n; i++) { 164 | a[i] ^= b[i]; 165 | } 166 | } 167 | 168 | // Xor the current cipher state by a specific round key 169 | static void xor_round_key(byte *state, const byte *keys, int round) { 170 | xor(state, keys + round * 16, 16); 171 | } 172 | 173 | // Apply the rijndael s-box to all elements in an array 174 | // http://en.wikipedia.org/wiki/Rijndael_S-box 175 | static void sub_bytes(byte *a, int n) { 176 | int i; 177 | for (i = 0; i < n; i++) { 178 | a[i] = lookup_sbox[a[i]]; 179 | } 180 | } 181 | static void sub_bytes_inv(byte *a, int n) { 182 | int i; 183 | for (i = 0; i < n; i++) { 184 | a[i] = lookup_sbox_inv[a[i]]; 185 | } 186 | } 187 | 188 | // Perform the core key schedule transform on 4 bytes, as part of the key expansion process 189 | // http://en.wikipedia.org/wiki/Rijndael_key_schedule#Key_schedule_core 190 | static void key_schedule_core(byte *a, int i) { 191 | byte temp = a[0]; // Rotate the output eight bits to the left 192 | a[0] = a[1]; 193 | a[1] = a[2]; 194 | a[2] = a[3]; 195 | a[3] = temp; 196 | sub_bytes(a, 4); // Apply Rijndael's S-box on all four individual bytes in the output word 197 | a[0] ^= lookup_rcon[i]; // On just the first (leftmost) byte of the output word, perform the rcon operation with i 198 | // as the input, and exclusive or the rcon output with the first byte of the output word 199 | } 200 | 201 | // Expand the 16-byte key to 11 round keys (176 bytes) 202 | // http://en.wikipedia.org/wiki/Rijndael_key_schedule#The_key_schedule 203 | void oqs_aes128_load_schedule_c(const uint8_t *key, void **_schedule) { 204 | *_schedule = malloc(16 * 11); 205 | assert(*_schedule != NULL); 206 | uint8_t *schedule = (uint8_t *) *_schedule; 207 | int bytes = 16; // The count of how many bytes we've created so far 208 | int i = 1; // The rcon iteration value i is set to 1 209 | int j; // For repeating the second stage 3 times 210 | byte t[4]; // Temporary working area known as 't' in the Wiki article 211 | memcpy(schedule, key, 16); // The first 16 bytes of the expanded key are simply the encryption key 212 | 213 | while (bytes < 176) { // Until we have 176 bytes of expanded key, we do the following: 214 | memcpy(t, schedule + bytes - 4, 4); // We assign the value of the previous four bytes in the expanded key to t 215 | key_schedule_core(t, i); // We perform the key schedule core on t, with i as the rcon iteration value 216 | i++; // We increment i by 1 217 | xor(t, schedule + bytes - 16, 4); // We exclusive-or t with the four-byte block 16 bytes before the new expanded key. 218 | memcpy(schedule + bytes, t, 4); // This becomes the next 4 bytes in the expanded key 219 | bytes += 4; // Keep track of how many expanded key bytes we've added 220 | 221 | // We then do the following three times to create the next twelve bytes 222 | for (j = 0; j < 3; j++) { 223 | memcpy(t, schedule + bytes - 4, 4); // We assign the value of the previous 4 bytes in the expanded key to t 224 | xor(t, schedule + bytes - 16, 4); // We exclusive-or t with the four-byte block n bytes before 225 | memcpy(schedule + bytes, t, 4); // This becomes the next 4 bytes in the expanded key 226 | bytes += 4; // Keep track of how many expanded key bytes we've added 227 | } 228 | } 229 | } 230 | 231 | void oqs_aes128_free_schedule_c(void *schedule) { 232 | if (schedule != NULL) { 233 | free(schedule); 234 | } 235 | } 236 | 237 | // Apply the shift rows step on the 16 byte cipher state 238 | // http://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_ShiftRows_step 239 | static void shift_rows(byte *state) { 240 | int i; 241 | byte temp[16]; 242 | memcpy(temp, state, 16); 243 | for (i = 0; i < 16; i++) { 244 | state[i] = temp[shift_rows_table[i]]; 245 | } 246 | } 247 | static void shift_rows_inv(byte *state) { 248 | int i; 249 | byte temp[16]; 250 | memcpy(temp, state, 16); 251 | for (i = 0; i < 16; i++) { 252 | state[i] = temp[shift_rows_table_inv[i]]; 253 | } 254 | } 255 | 256 | // Perform the mix columns matrix on one column of 4 bytes 257 | // http://en.wikipedia.org/wiki/Rijndael_mix_columns 258 | static void mix_col(byte *state) { 259 | byte a0 = state[0]; 260 | byte a1 = state[1]; 261 | byte a2 = state[2]; 262 | byte a3 = state[3]; 263 | state[0] = lookup_g2[a0] ^ lookup_g3[a1] ^ a2 ^ a3; 264 | state[1] = lookup_g2[a1] ^ lookup_g3[a2] ^ a3 ^ a0; 265 | state[2] = lookup_g2[a2] ^ lookup_g3[a3] ^ a0 ^ a1; 266 | state[3] = lookup_g2[a3] ^ lookup_g3[a0] ^ a1 ^ a2; 267 | } 268 | 269 | // Perform the mix columns matrix on each column of the 16 bytes 270 | static void mix_cols(byte *state) { 271 | mix_col(state); 272 | mix_col(state + 4); 273 | mix_col(state + 8); 274 | mix_col(state + 12); 275 | } 276 | 277 | // Perform the inverse mix columns matrix on one column of 4 bytes 278 | // http://en.wikipedia.org/wiki/Rijndael_mix_columns 279 | static void mix_col_inv(byte *state) { 280 | byte a0 = state[0]; 281 | byte a1 = state[1]; 282 | byte a2 = state[2]; 283 | byte a3 = state[3]; 284 | state[0] = lookup_g14[a0] ^ lookup_g9[a3] ^ lookup_g13[a2] ^ lookup_g11[a1]; 285 | state[1] = lookup_g14[a1] ^ lookup_g9[a0] ^ lookup_g13[a3] ^ lookup_g11[a2]; 286 | state[2] = lookup_g14[a2] ^ lookup_g9[a1] ^ lookup_g13[a0] ^ lookup_g11[a3]; 287 | state[3] = lookup_g14[a3] ^ lookup_g9[a2] ^ lookup_g13[a1] ^ lookup_g11[a0]; 288 | } 289 | 290 | // Perform the inverse mix columns matrix on each column of the 16 bytes 291 | static void mix_cols_inv(byte *state) { 292 | mix_col_inv(state); 293 | mix_col_inv(state + 4); 294 | mix_col_inv(state + 8); 295 | mix_col_inv(state + 12); 296 | } 297 | 298 | void oqs_aes128_enc_c(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext) { 299 | const uint8_t *schedule = (const uint8_t *) _schedule; 300 | int i; // To count the rounds 301 | 302 | // First Round 303 | memcpy(ciphertext, plaintext, 16); 304 | xor_round_key(ciphertext, schedule, 0); 305 | 306 | // Middle rounds 307 | for (i = 0; i < 9; i++) { 308 | sub_bytes(ciphertext, 16); 309 | shift_rows(ciphertext); 310 | mix_cols(ciphertext); 311 | xor_round_key(ciphertext, schedule, i + 1); 312 | } 313 | 314 | // Final Round 315 | sub_bytes(ciphertext, 16); 316 | shift_rows(ciphertext); 317 | xor_round_key(ciphertext, schedule, 10); 318 | } 319 | 320 | // It's not enc nor dec, it's something in between 321 | void oqs_mhy128_enc_c(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext) { 322 | const uint8_t *schedule = (const uint8_t *) _schedule; 323 | int i; // To count the rounds 324 | 325 | // First Round 326 | memcpy(ciphertext, plaintext, 16); 327 | xor_round_key(ciphertext, schedule, 0); 328 | 329 | // Middle rounds 330 | for (i = 0; i < 9; i++) { 331 | sub_bytes_inv(ciphertext, 16); 332 | shift_rows_inv(ciphertext); 333 | mix_cols_inv(ciphertext); 334 | xor_round_key(ciphertext, schedule, i + 1); 335 | } 336 | 337 | // Final Round 338 | sub_bytes_inv(ciphertext, 16); 339 | shift_rows_inv(ciphertext); 340 | xor_round_key(ciphertext, schedule, 10); 341 | } 342 | 343 | void oqs_aes128_dec_c(const uint8_t *ciphertext, const void *_schedule, uint8_t *plaintext) { 344 | const uint8_t *schedule = (const uint8_t *) _schedule; 345 | int i; // To count the rounds 346 | 347 | // Reverse the final Round 348 | memcpy(plaintext, ciphertext, 16); 349 | xor_round_key(plaintext, schedule, 10); 350 | shift_rows_inv(plaintext); 351 | sub_bytes_inv(plaintext, 16); 352 | 353 | // Reverse the middle rounds 354 | for (i = 0; i < 9; i++) { 355 | xor_round_key(plaintext, schedule, 9 - i); 356 | mix_cols_inv(plaintext); 357 | shift_rows_inv(plaintext); 358 | sub_bytes_inv(plaintext, 16); 359 | } 360 | 361 | // Reverse the first Round 362 | xor_round_key(plaintext, schedule, 0); 363 | } 364 | 365 | void oqs_mhy128_dec_c(const uint8_t *ciphertext, const void *_schedule, uint8_t *plaintext) { 366 | const uint8_t *schedule = (const uint8_t *) _schedule; 367 | int i; // To count the rounds 368 | 369 | // Reverse the final Round 370 | memcpy(plaintext, ciphertext, 16); 371 | xor_round_key(plaintext, schedule, 10); 372 | shift_rows(plaintext); 373 | sub_bytes(plaintext, 16); 374 | 375 | // Reverse the middle rounds 376 | for (i = 0; i < 9; i++) { 377 | xor_round_key(plaintext, schedule, 9 - i); 378 | mix_cols(plaintext); 379 | shift_rows(plaintext); 380 | sub_bytes(plaintext, 16); 381 | } 382 | 383 | // Reverse the first Round 384 | xor_round_key(plaintext, schedule, 0); 385 | } 386 | --------------------------------------------------------------------------------