azure-protected-vm-secrets/System.cpp (143 lines of code) (raw):
#include "pch.h"
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>
#ifdef PLATFORM_UNIX
#include <fstream>
#else PLATFORM_UNIX
#include <windows.h>
struct RawSMBIOSData
{
BYTE Used20CallingMethod;
BYTE SMBIOSMajorVersion;
BYTE SMBIOSMinorVersion;
BYTE DmiRevision;
DWORD Size;
BYTE SMBIOSTableData[];
};
struct SmBiosStructure
{
BYTE Type;
BYTE Length;
WORD Handle;
};
struct SystemInfo : SmBiosStructure
{
BYTE Manufacturer;
BYTE ProductName;
BYTE Version;
BYTE SerialNumber;
// Ver 2.1+
BYTE UUID[16];
BYTE Wakeup_Type;
// Ver 2.4+
BYTE SKUNumber;
BYTE Family;
};
#endif
struct UUID
{
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
};
unsigned int GetSystemSmBios(unsigned char **outUuid)
{
#ifndef PLATFORM_UNIX
DWORD smbiosSize = 0;
UINT actualSize = GetSystemFirmwareTable('RSMB', 0, NULL, smbiosSize);
if (actualSize == 0)
{
return 0;
}
PUCHAR smbiosBuffer = (PUCHAR)malloc(actualSize);
if (smbiosBuffer == NULL)
{
return 0;
}
smbiosSize = GetSystemFirmwareTable('RSMB', 0, smbiosBuffer, actualSize);
RawSMBIOSData* smbiosData = (RawSMBIOSData*)smbiosBuffer;
ULONG i = 0;
SmBiosStructure* smBiosStructure = NULL;
bool properTermination = false;
do
{
properTermination = false;
// Check that the buffer contains at least one whole structure header
if (i + sizeof(SmBiosStructure) < smbiosData->Size)
{
if (smbiosData->SMBIOSTableData[i] == 1)
{
// Found structure that matches type
smBiosStructure = (SmBiosStructure*)&smbiosData->SMBIOSTableData[i];
}
// Jump to the end of the structure header
i += smbiosData->SMBIOSTableData[i + 1];
// Look for a double-null (\0\0), which indicates the end of the structure
while (i + 1 < smbiosData->Size)
{
if ((smbiosData->SMBIOSTableData[i] == 0) && (smbiosData->SMBIOSTableData[i + 1] == 0))
{
properTermination = true;
i += 2;
break;
}
++i;
}
}
} while (properTermination && !smBiosStructure);
*outUuid = ((SystemInfo*)smBiosStructure)->UUID;
return 16;
#else
#endif
}
std::string formatUUID(char* uuid, int size) {
if (size == 0)
{
return "";
}
std::string uuidStr = "";
struct UUID* uuid_t = (struct UUID*)uuid;
std::ostringstream oss;
oss << std::uppercase << std::hex << std::right << std::setfill('0');
oss << std::setw(8) << uuid_t->Data1 << "-";
oss << std::setw(4) << uuid_t->Data2 << "-";
oss << std::setw(4) << uuid_t->Data3 << "-";
oss << std::setw(2) << (int)uuid_t->Data4[0];
oss << std::setw(2) << (int)uuid_t->Data4[1] << "-";
for (int i = 2; i < 8; i++)
{
oss << std::setw(2) << (int)uuid_t->Data4[i];
}
return oss.str();
}
std::string GetSystemUuid()
{
#ifndef PLATFORM_UNIX
unsigned char* uuid = NULL;
unsigned int size = GetSystemSmBios(&uuid);
return formatUUID((char*)uuid, size);
#else
std::ifstream file("/sys/class/dmi/id/product_uuid");
std::string uuid;
if (file.is_open()) {
std::getline(file, uuid);
file.close();
} else {
throw std::runtime_error("Unable to open /sys/class/dmi/id/product_uuid");
}
return uuid;
#endif
}
unsigned int GetVmid()
{
unsigned char* uuid = NULL;
unsigned int size = GetSystemSmBios(&uuid);
if (size == 0)
{
return 0;
}
unsigned int vmid = 0;
for (int i = 0; i < 16; i++)
{
printf("%02X", uuid[i]);
}
printf("\n");
return vmid;
}