nonce.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include "nonce.h"
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <sys/stat.h>
  7. #include <mach/mach.h>
  8. #include "IOKit.h"
  9. #include <CoreFoundation/CoreFoundation.h>
  10. #include "debug.h"
  11. #define kIONVRAMDeletePropertyKey "IONVRAM-DELETE-PROPERTY"
  12. #define kIONVRAMForceSyncNowPropertyKey "IONVRAM-FORCESYNCNOW-PROPERTY"
  13. #define nonceKey "com.apple.System.boot-nonce"
  14. // thx PhoenixNonce
  15. CFMutableDictionaryRef makedict(const char *key, const char *val) {
  16. CFStringRef cfkey = CFStringCreateWithCStringNoCopy(NULL, key, kCFStringEncodingUTF8, kCFAllocatorNull);
  17. CFStringRef cfval = CFStringCreateWithCStringNoCopy(NULL, val, kCFStringEncodingUTF8, kCFAllocatorNull);
  18. CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
  19. if(!cfkey || !dict || !cfval) {
  20. ERROR("failed to alloc cf objects {'%s': '%s'}", key, val);
  21. return NULL;
  22. } else {
  23. DEBUG("made dict {'%s': '%s'}", key, val);
  24. }
  25. CFDictionarySetValue(dict, cfkey, cfval);
  26. CFRelease(cfkey);
  27. CFRelease(cfval);
  28. return dict;
  29. }
  30. int applydict(CFMutableDictionaryRef dict) {
  31. int ret = 1;
  32. io_service_t nvram = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODTNVRAM"));
  33. if(!MACH_PORT_VALID(nvram)) {
  34. ERROR("Failed to get IODTNVRAM service");
  35. } else {
  36. kern_return_t kret = IORegistryEntrySetCFProperties(nvram, dict);
  37. DEBUG("IORegistryEntrySetCFProperties: 0x%x (%s)\n", kret, mach_error_string(kret));
  38. if(kret == KERN_SUCCESS) {
  39. ret = 0;
  40. }
  41. }
  42. IOObjectRelease(nvram);
  43. return ret;
  44. }
  45. char* getval(const char *key) {
  46. // IORegistryEntryCreateCFProperty seems to fail, btw
  47. char buf[1024];
  48. unsigned int length = sizeof(buf);
  49. kern_return_t err;
  50. io_service_t nvram = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODTNVRAM"));
  51. if(!MACH_PORT_VALID(nvram)) {
  52. ERROR("Failed to get IODTNVRAM service");
  53. return NULL;
  54. }
  55. err = IORegistryEntryGetProperty(nvram, key, (void*)buf, &length);
  56. IOObjectRelease(nvram);
  57. DEBUG("IORegistryEntryGetProperty(%s) == 0x%x (%s)\n", key, err, mach_error_string(err));
  58. if (err != KERN_SUCCESS) {
  59. return NULL;
  60. }
  61. buf[length] = '\0';
  62. return strdup(buf);
  63. }
  64. int makenapply(const char *key, const char *val) {
  65. int ret = 1;
  66. CFMutableDictionaryRef dict = makedict(key, val);
  67. if(!dict) {
  68. ERROR("failed to make cf dict\n");
  69. return ret;
  70. }
  71. ret = applydict(dict);
  72. if (ret) {
  73. ERROR("applydict failed\n");
  74. }
  75. CFRelease(dict);
  76. return ret;
  77. }
  78. int setgen(const char *gen) {
  79. int ret = 0;
  80. ret = makenapply(kIONVRAMDeletePropertyKey, nonceKey);
  81. // set even if delete failed
  82. ret = makenapply(nonceKey, gen);
  83. ret = ret || makenapply(kIONVRAMForceSyncNowPropertyKey, nonceKey);
  84. return ret;
  85. }
  86. char* getgen(void) {
  87. return getval(nonceKey);
  88. }
  89. int delgen(void) {
  90. return makenapply(kIONVRAMDeletePropertyKey, nonceKey);
  91. }