SecCoreAnalytics.m
1 /* 2 * Copyright (c) 2018 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 #import "SecCoreAnalytics.h" 25 #import <CoreAnalytics/CoreAnalytics.h> 26 #import <SoftLinking/SoftLinking.h> 27 #import <Availability.h> 28 #import <sys/sysctl.h> 29 30 NSString* const SecCoreAnalyticsValue = @"value"; 31 32 33 void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value) 34 { 35 [SecCoreAnalytics sendEvent:(__bridge NSString*)eventName 36 event:@{ 37 SecCoreAnalyticsValue: [NSNumber numberWithLong:value], 38 }]; 39 } 40 41 void SecCoreAnalyticsSendKernEntropyHealth() 42 { 43 size_t sz_int = sizeof(int); 44 size_t sz_uint = sizeof(unsigned int); 45 size_t sz_tv = sizeof(struct timeval); 46 47 int startup_done; 48 unsigned int adaptive_proportion_failure_count = 0; 49 unsigned int adaptive_proportion_max_observation_count = 0; 50 unsigned int adaptive_proportion_reset_count = 0; 51 unsigned int repetition_failure_count = 0; 52 unsigned int repetition_max_observation_count = 0; 53 unsigned int repetition_reset_count = 0; 54 55 int rv = sysctlbyname("kern.entropy.health.startup_done", &startup_done, &sz_int, NULL, 0); 56 rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.failure_count", &adaptive_proportion_failure_count, &sz_uint, NULL, 0); 57 rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.max_observation_count", &adaptive_proportion_max_observation_count, &sz_uint, NULL, 0); 58 rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.reset_count", &adaptive_proportion_reset_count, &sz_uint, NULL, 0); 59 rv |= sysctlbyname("kern.entropy.health.repetition_count_test.failure_count", &repetition_failure_count, &sz_uint, NULL, 0); 60 rv |= sysctlbyname("kern.entropy.health.repetition_count_test.max_observation_count", &repetition_max_observation_count, &sz_uint, NULL, 0); 61 rv |= sysctlbyname("kern.entropy.health.repetition_count_test.reset_count", &repetition_reset_count, &sz_uint, NULL, 0); 62 63 // Round up to next power of two. 64 if (adaptive_proportion_reset_count > 0) { 65 adaptive_proportion_reset_count = 66 1U << (sizeof(unsigned int) * 8 - __builtin_clz(adaptive_proportion_reset_count)); 67 } 68 69 // Round up to next power of two. 70 if (repetition_reset_count > 0) { 71 repetition_reset_count = 72 1U << (sizeof(unsigned int) * 8 - __builtin_clz(repetition_reset_count)); 73 } 74 75 // Default to not submitting uptime, except on failure. 76 int uptime = -1; 77 78 if (adaptive_proportion_failure_count > 0 || repetition_failure_count > 0) { 79 time_t now; 80 time(&now); 81 82 struct timeval boottime; 83 int mib[2] = { CTL_KERN, KERN_BOOTTIME }; 84 rv |= sysctl(mib, 2, &boottime, &sz_tv, NULL, 0); 85 86 // Submit uptime in minutes. 87 uptime = (int)((now - boottime.tv_sec) / 60); 88 } 89 90 if (rv) { 91 return; 92 } 93 94 [SecCoreAnalytics sendEventLazy:@"com.apple.kern.entropyHealth" builder:^NSDictionary<NSString *,NSObject *> * _Nonnull{ 95 return @{ 96 @"uptime" : @(uptime), 97 @"startup_done" : @(startup_done), 98 @"adaptive_proportion_failure_count" : @(adaptive_proportion_failure_count), 99 @"adaptive_proportion_max_observation_count" : @(adaptive_proportion_max_observation_count), 100 @"adaptive_proportion_reset_count" : @(adaptive_proportion_reset_count), 101 @"repetition_failure_count" : @(repetition_failure_count), 102 @"repetition_max_observation_count" : @(repetition_max_observation_count), 103 @"repetition_reset_count" : @(repetition_reset_count) 104 }; 105 }]; 106 } 107 108 @implementation SecCoreAnalytics 109 110 SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CoreAnalytics); 111 112 SOFT_LINK_FUNCTION(CoreAnalytics, AnalyticsSendEvent, soft_AnalyticsSendEvent, \ 113 void, (NSString* eventName, NSDictionary<NSString*,NSObject*>* eventPayload),(eventName, eventPayload)); 114 SOFT_LINK_FUNCTION(CoreAnalytics, AnalyticsSendEventLazy, soft_AnalyticsSendEventLazy, \ 115 void, (NSString* eventName, NSDictionary<NSString*,NSObject*>* (^eventPayloadBuilder)(void)),(eventName, eventPayloadBuilder)); 116 117 + (void)sendEvent:(NSString*) eventName event:(NSDictionary<NSString*,NSObject*>*)event 118 { 119 if (isCoreAnalyticsAvailable()) { 120 soft_AnalyticsSendEvent(eventName, event); 121 } 122 } 123 124 + (void)sendEventLazy:(NSString*) eventName builder:(NSDictionary<NSString*,NSObject*>* (^)(void))builder 125 { 126 if (isCoreAnalyticsAvailable()) { 127 soft_AnalyticsSendEventLazy(eventName, builder); 128 } 129 } 130 131 @end