diff --git a/native/serverconnection/src/hwuid.cpp b/native/serverconnection/src/hwuid.cpp index 09cb289..462089f 100644 --- a/native/serverconnection/src/hwuid.cpp +++ b/native/serverconnection/src/hwuid.cpp @@ -1,4 +1,4 @@ -#include "hwuid.h" +#include "./hwuid.h" #include #include #include @@ -94,15 +94,105 @@ inline bool generate_uuid(std::string& result, uint32_t& check_sum) { } return true; } - #else - #error Implement me! +#include "./smbios.h" +#include +#include +#include + +using namespace std; + +//https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf +int get_uuid(uint8_t* uuid) { + unique_ptr smbios_data{ nullptr, ::free }; + size_t smbios_size = 0; + size_t bytes_written = 0; + + // Query size of SMBIOS data. + smbios_size = GetSystemFirmwareTable('RSMB', 0, nullptr, 0); + smbios_data.reset((SMBIOSDataHeader*) malloc(smbios_size)); + if (!smbios_data) return -1; //failed to allocate memory + + bytes_written = GetSystemFirmwareTable('RSMB', 0, &*smbios_data, smbios_size); + + if (smbios_size != bytes_written) return -2; //failed to read the firmware table + + if (smbios_data->length > bytes_written - SMBIOSDataHeaderLength) return -3; //invalid length + + //Lets iterate over the headers: + uint8_t* ptr = &smbios_data->table_data; + SMBIOSEntryHeader* header; + while (true) { + header = (SMBIOSEntryHeader*) ptr; + if (header->type == 127 && header->length == 4) { + break; //End marker + } + + if (header->type == 1) { + //Type 1: System Information + if (header->length < 0x18) { + //If version is under 2.1 no uuid is set! + //TODO: Check before for the version? + return -4; //system information table is too short + } + + memcpy(uuid, ptr + 0x08, 16); + return 0; + } + + ptr = ptr + header->length; // point to struct end + while (0 != (*ptr | *(ptr + 1)) && *ptr < (uint8_t) &*smbios_data + smbios_data->length) + ptr++; // skip string area + + ptr += 2; + if (ptr >= (uint8_t*) &*smbios_data + smbios_data->length - 2) + break; + } + return -6; +} + +uint32_t calculate_cpu_hash() { + int cpuinfo[4] = { 0, 0, 0, 0 }; + __cpuid(cpuinfo, 0); + + uint32_t hash = 0; + auto ptr = (uint32_t*) (&cpuinfo[0]); + for (uint32_t i = 0; i < 4; i++) + hash += ptr[i]; + + return hash; +} + +inline bool generate_uuid(std::string& result, uint32_t& check_sum) { + uint8_t buffer[16]; + auto code = get_uuid(buffer); + if(code != 0) { + memcpy(buffer, "DDDDCCCCBBBBAAAA", 16); /* Reversed to linux (just for the foxic) */ + buffer[15] = code; /* So we could get the error code */ + } + + auto cpu_hash = calculate_cpu_hash(); + auto it = (uint32_t*) buffer; + for(int i = 0; i < 4; i++) + *it++ = cpu_hash; + + result = base64::encode((char*) buffer, 16); + + { + crc32_state state; + crc32_init(&state); + crc32_update(&state, (u_char*) result.data(), result.length()); + + crc32_finish(&state, &check_sum, sizeof(check_sum)); + } + return true; +} #endif inline bool check_uuid(std::string& uuid, uint32_t check_sum) { crc32_state state; crc32_init(&state); - crc32_update(&state, (u_char*) uuid.data(), uuid.length()); + crc32_update(&state, (uint8_t*) uuid.data(), uuid.length()); uint32_t result; crc32_finish(&state, &result, sizeof(result)); @@ -121,49 +211,10 @@ std::string system_uuid() { return _cached_system_uuid; } -/* - -"Hello World": Avg raw: 18ms Avg obf: 20ms - -#include -using namespace std::chrono; int main() { - #define TEST_MESSAGE ("Hello World I'm a bit longer that 50 character string! Hello World I'm a bit longer that 50 character string! Hello World I'm a bit longer that 50 character string! Hello World I'm a bit longer that 50 character string! Hello World I'm a bit longer that 50 character string! Hello World I'm a bit longer that 50 character string!") - - system_clock::time_point begin, end; - size_t sum_raw = 0, sum_obf = 0, runs = 50; - - std::cerr << "Testing raw\n"; - for(int i = 0; i < runs; i++) { - begin = system_clock::now(); - for(size_t index = 0; index < 1e6; index++) { - puts(TEST_MESSAGE); - } - end = system_clock::now(); - - auto ms = floor(end - begin).count(); - sum_raw += ms; - //std::cerr << "Raw test took " << ms << "ms\n"; - } - - std::cerr << "Testing obf\n"; - for(int i = 0; i < runs; i++) { - begin = system_clock::now(); - for(size_t index = 0; index < 1e6; index++) { - puts(strobf(TEST_MESSAGE).c_str()); - } - end = system_clock::now(); - - auto ms = floor(end - begin).count(); - sum_obf += ms; - //std::cerr << "Obf test took " << ms << "ms\n"; - } - std::cerr << "Avg raw: " << (sum_raw / runs) << "ms Avg obf: " << (sum_obf / runs) << "ms\n"; - - //std::cout << "UUID: " << system_uuid() << "\n"; + std::cout << "UUID: " << system_uuid() << "\n"; return 1; } //ADaX2mIRrC1uv83h - - */ \ No newline at end of file +//NEg5KzRIOSs0SDkrNEg5Kw== \ No newline at end of file diff --git a/native/serverconnection/src/smbios.h b/native/serverconnection/src/smbios.h new file mode 100644 index 0000000..7520e88 --- /dev/null +++ b/native/serverconnection/src/smbios.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#pragma pack(push) +#pragma pack(1) +typedef struct _SMBIOSDataHeader +{ + uint8_t _unused; + uint8_t major_version; + uint8_t minor_version; + uint8_t dmi_revision; + uint32_t length; + + uint8_t table_data; +} SMBIOSDataHeader; + +static constexpr size_t SMBIOSDataHeaderLength = 8; +static_assert(sizeof(SMBIOSDataHeader) == SMBIOSDataHeaderLength + 1, "invalid struct size"); + + +typedef struct _SMBIOSEntryHeader +{ + uint8_t type; + uint8_t length; + uint16_t header; + + uint8_t data; +} SMBIOSEntryHeader; + +static constexpr size_t SMBIOSEntryHeaderLength = 4; +static_assert(sizeof(SMBIOSEntryHeader) == SMBIOSEntryHeaderLength + 1, "invalid struct size"); + +#pragma pack(pop) \ No newline at end of file