You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hashcat/src/ext_iokit.c

369 lines
8.3 KiB

/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#include "common.h"
#include "types.h"
#include "memory.h"
#include "shared.h"
#include "event.h"
#include "ext_iokit.h"
#if defined (__APPLE__)
#include <IOKit/IOKitLib.h>
UInt32 hm_IOKIT_strtoul (const char *str, int size, int base)
{
int i;
UInt32 total = 0;
for (i = 0; i < size; i++)
{
if (base == 16)
{
total += str[i] << (size - 1 - i) * 8;
}
else
{
total += (unsigned char) (str[i] << (size - 1 - i) * 8);
}
}
return total;
}
void hm_IOKIT_ultostr (char *str, UInt32 val)
{
str[0] = '\0';
snprintf (str, 5, "%c%c%c%c", (unsigned int) (val >> 24), (unsigned int) (val >> 16), (unsigned int) (val >> 8), (unsigned int) (val));
}
kern_return_t hm_IOKIT_SMCOpen (void *hashcat_ctx, io_connect_t *conn)
{
kern_return_t result;
io_iterator_t iterator;
io_object_t device;
CFMutableDictionaryRef matchingDictionary = IOServiceMatching ("AppleSMC");
result = IOServiceGetMatchingServices (hc_IOMasterPortDefault, matchingDictionary, &iterator);
if (result != kIOReturnSuccess)
{
event_log_error (hashcat_ctx, "IOServiceGetMatchingServices(): %08x", result);
return 1;
}
device = IOIteratorNext (iterator);
IOObjectRelease (iterator);
if (device == 0)
{
event_log_error (hashcat_ctx, "hm_IOKIT_SMCOpen(): no SMC found.");
return 1;
}
result = IOServiceOpen (device, mach_task_self (), 0, conn);
IOObjectRelease (device);
if (result != kIOReturnSuccess)
{
event_log_error (hashcat_ctx, "IOServiceOpen(): %08x", result);
return 1;
}
return kIOReturnSuccess;
}
kern_return_t hm_IOKIT_SMCClose (io_connect_t conn)
{
return IOServiceClose (conn);
}
kern_return_t hm_IOKIT_SMCCall (int index, SMCKeyData_t *inData, SMCKeyData_t *outData, io_connect_t conn)
{
size_t inDataSize = sizeof (SMCKeyData_t);
size_t outDataSize = sizeof (SMCKeyData_t);
#if MAC_OS_X_VERSION_10_5
return IOConnectCallStructMethod (conn, index, inData, inDataSize, outData, &outDataSize);
#else
return IOConnectMethodStructureIStructureO (conn, index, inDataSize, &outDataSize, inData, outData);
#endif
}
kern_return_t hm_IOKIT_SMCReadKey (UInt32Char_t key, SMCVal_t *val, io_connect_t conn)
{
SMCKeyData_t inData;
SMCKeyData_t outData;
memset (&inData, 0, sizeof (SMCKeyData_t));
memset (&outData, 0, sizeof (SMCKeyData_t));
memset (val, 0, sizeof (SMCVal_t));
inData.key = hm_IOKIT_strtoul (key, 4, 16);
inData.data8 = SMC_CMD_READ_KEYINFO;
if (hm_IOKIT_SMCCall (KERNEL_INDEX_SMC, &inData, &outData, conn) != kIOReturnSuccess) return 1;
val->dataSize = outData.keyInfo.dataSize;
hm_IOKIT_ultostr (val->dataType, outData.keyInfo.dataType);
inData.keyInfo.dataSize = val->dataSize;
inData.data8 = SMC_CMD_READ_BYTES;
if (hm_IOKIT_SMCCall (KERNEL_INDEX_SMC, &inData, &outData, conn) != kIOReturnSuccess) return 1;
memcpy (val->bytes, outData.bytes, sizeof (outData.bytes));
return kIOReturnSuccess;
}
int hm_IOKIT_SMCGetSensorGraphicHot (void *hashcat_ctx)
{
hwmon_ctx_t *hwmon_ctx = ((hashcat_ctx_t *) hashcat_ctx)->hwmon_ctx;
IOKIT_PTR *iokit = hwmon_ctx->hm_iokit;
SMCVal_t val;
memset (&val, 0, sizeof (SMCVal_t));
if (hm_IOKIT_SMCReadKey (HM_IOKIT_SMC_SENSOR_GRAPHICS_HOT, &val, iokit->conn) == kIOReturnSuccess)
{
int alarm = -1;
if (val.dataSize > 0)
{
if (strcmp (val.dataType, DATATYPE_UINT8) == 0)
{
alarm = hm_IOKIT_strtoul ((char *) val.bytes, val.dataSize, 10);
}
}
return alarm;
}
return -1;
}
int hm_IOKIT_SMCGetTemperature (void *hashcat_ctx, char *key, double *temp)
{
hwmon_ctx_t *hwmon_ctx = ((hashcat_ctx_t *) hashcat_ctx)->hwmon_ctx;
IOKIT_PTR *iokit = hwmon_ctx->hm_iokit;
SMCVal_t val;
memset (&val, 0, sizeof (SMCVal_t));
if (hm_IOKIT_SMCReadKey (key, &val, iokit->conn) == kIOReturnSuccess)
{
if (val.dataSize > 0)
{
if (strcmp (val.dataType, DATATYPE_SP78) == 0)
{
// convert sp78 value to temperature
int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1];
*temp = (intValue / 256.0);
return 1;
}
}
}
// read failed
*temp = 0.0;
return -1;
}
bool hm_IOKIT_SMCGetFanRPM (char *key, io_connect_t conn, float *ret)
{
SMCVal_t val;
memset (&val, 0, sizeof (SMCVal_t));
if (hm_IOKIT_SMCReadKey (key, &val, conn) == kIOReturnSuccess)
{
if (val.dataSize > 0)
{
if (strcmp (val.dataType, DATATYPE_FLT) == 0)
{
*ret = *(float *) val.bytes;
return true;
}
if (strcmp (val.dataType, DATATYPE_FPE2) == 0)
{
// convert fpe2 value to RPM
*ret = ntohs (*(UInt16*) val.bytes) / 4.0;
return true;
}
}
}
// read failed
*ret = -1.f;
return false;
}
int hm_IOKIT_get_utilization_current (void *hashcat_ctx, int *utilization)
{
bool rc = false;
io_iterator_t iterator;
CFMutableDictionaryRef matching = IOServiceMatching ("IOAccelerator");
if (IOServiceGetMatchingServices (hc_IOMasterPortDefault, matching, &iterator) != kIOReturnSuccess)
{
event_log_error (hashcat_ctx, "IOServiceGetMatchingServices(): failure");
return rc;
}
io_registry_entry_t regEntry;
while ((regEntry = IOIteratorNext (iterator)))
{
// Put this services object into a dictionary object.
CFMutableDictionaryRef serviceDictionary;
if (IORegistryEntryCreateCFProperties (regEntry, &serviceDictionary, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
// Service dictionary creation failed.
IOObjectRelease (regEntry);
continue;
}
CFMutableDictionaryRef perf_properties = (CFMutableDictionaryRef) CFDictionaryGetValue (serviceDictionary, CFSTR ("PerformanceStatistics"));
if (perf_properties)
{
static ssize_t gpuCoreUtil = 0;
const void *gpuCoreUtilization = CFDictionaryGetValue (perf_properties, CFSTR ("Device Utilization %"));
if (gpuCoreUtilization != NULL)
{
CFNumberGetValue (gpuCoreUtilization, kCFNumberSInt64Type, &gpuCoreUtil);
*utilization = gpuCoreUtil;
rc = true;
}
}
CFRelease (serviceDictionary);
IOObjectRelease (regEntry);
if (rc == true) break;
}
IOObjectRelease (iterator);
return rc;
}
int hm_IOKIT_get_fan_speed_current (void *hashcat_ctx, char *fan_speed_buf)
{
hwmon_ctx_t *hwmon_ctx = ((hashcat_ctx_t *) hashcat_ctx)->hwmon_ctx;
IOKIT_PTR *iokit = hwmon_ctx->hm_iokit;
SMCVal_t val;
UInt32Char_t key;
memset (&val, 0, sizeof (SMCVal_t));
if (hm_IOKIT_SMCReadKey ("FNum", &val, iokit->conn) == kIOReturnSuccess)
{
int totalFans = hm_IOKIT_strtoul ((char *)val.bytes, val.dataSize, 10);
if (totalFans <= 0) return -1;
// limit totalFans to 10
if (totalFans > 10) totalFans = 10;
char tmp_buf[16];
for (int i = 0; i < totalFans; i++)
{
int fan_speed = 0;
float actual_speed = 0.0f;
float maximum_speed = 0.0f;
memset (&key, 0, sizeof (UInt32Char_t));
snprintf (key, 5, "F%dAc", i);
hm_IOKIT_SMCGetFanRPM (key, iokit->conn, &actual_speed);
if (actual_speed < 0.f) continue;
memset (&key, 0, sizeof (UInt32Char_t));
snprintf (key, 5, "F%dMx", i);
hm_IOKIT_SMCGetFanRPM (key, iokit->conn, &maximum_speed);
if (maximum_speed < 0.f) continue;
fan_speed = (actual_speed / maximum_speed) * 100.f;
memset (tmp_buf, 0, sizeof (tmp_buf));
snprintf (tmp_buf, sizeof (tmp_buf) - 1, "Fan%d: %d%%, ", i, fan_speed);
strncat (fan_speed_buf, tmp_buf, strlen (tmp_buf));
}
// remove last two bytes
size_t out_len = strlen (fan_speed_buf);
if (out_len > 2) fan_speed_buf[out_len-2] = '\0';
}
return 1;
}
bool iokit_init (void *hashcat_ctx)
{
hwmon_ctx_t *hwmon_ctx = ((hashcat_ctx_t *) hashcat_ctx)->hwmon_ctx;
IOKIT_PTR *iokit = hwmon_ctx->hm_iokit;
memset (iokit, 0, sizeof (IOKIT_PTR));
if (hm_IOKIT_SMCOpen (hashcat_ctx, &iokit->conn) == kIOReturnSuccess) return true;
hcfree (hwmon_ctx->hm_iokit);
hwmon_ctx->hm_iokit = NULL;
return false;
}
bool iokit_close (void *hashcat_ctx)
{
hwmon_ctx_t *hwmon_ctx = ((hashcat_ctx_t *) hashcat_ctx)->hwmon_ctx;
IOKIT_PTR *iokit = hwmon_ctx->hm_iokit;
hm_IOKIT_SMCClose (iokit->conn);
return true;
}
#endif // __APPLE__